Свойство индексатор в c builder

Я уже описал основные поддерживаемые С типы, способы их объявления и использования в классах и приложениях. А теперь мы нарушим порядок изложения, при котором каждая глава посвящена описанию какой-либо одной из важных функций языка, — в этой главе вы узнаете о свойствах, массивах и индексаторах, так как у этих функций языка много общего.

Они позволяют разработчику классов на С расширять возможности базовых структур классов полей и методов , чтобы члены классов предоставляли более понятный и естественный интерфейс. Всегда поощряется создание классов, которые не только скрывают реализацию своих методов, но и запрещают членам любой прямой доступ к полям класса.

Обеспечить корректную работу с полем можно, предоставляя методы-аксессоры accessor methods , выполняющие работу по получению и установке значений этих полей, так чтобы они действовали согласно правилам конкретной предметной области. Допустим, у вас есть класс "Адрес" с полями для почтового индекса и города. Когда клиент модифицирует поле индекса Address. ZipCode, вам нужно сверить введенный код с БД и автоматически установить значение поля Address.

City в зависимости от этого почтового индекса. Если бы у клиента был прямой доступ к открытому члену public Address. ZipCode, выполнить обе эти задачи было бы сложно, поскольку для непосредственного изменения открытого члена метод не требуется. Поэтому вместо того, чтобы предоставить доступ к полю Address. ZipCode, лучше определить поля Address. City как protected и предоставить методы-аксессоры для получения и установки значения поля Address.

Таким образом, вы можете добавить код, выполняющий дополнительную работу при изменении поля. Этот пример с почтовым индексом можно запрограммировать на С следующим образом.

City no результатам проверки почтового. Однако С предоставляет еще более мощный механизм — свойства с такими же возможностями, как методы-аксессоры, но гораздо более элегантные на стороне клиента. Свойства позволяют написать клиент, способный обращаться к полям класса, как если бы они были открытыми, даже не зная, существуют ли методы-аксессоры. Свойство в С состоит из объявления поля и методов-аксессоров, применяемых для изменения значения поля. Эти методы-аксессоры называются получатель getter и установщик setter.

Методы-получатели используются для получения значения поля, а установщики — для его изменения. Вот наш пример, переписанный с применением свойств С: Я создал поле Address. Поначалу это может ввести в заблуждение: ZipCode — это поле, да еще и определенное дважды. Но это не поле, а свойство, представляющее собой универсальное средство определения аксессоров для членов класса, что позволяет использовать более интуитивно понятный синтаксис вида объект, поле.

Если бы я опустил в этом примере поле Address. Заметьте также, что установщик не принимает аргументов. Передаваемое значение автоматически помещается в переменную value, доступную внутри метода-установщика вскоре с помощью MSIL вы увидите, как происходит это маленькое чудо.

А теперь, написав свойство Address. ZipCode, рассмотрим изменения, которые необходимо сделать для клиентского кода: Как видите, способ обращения клиента к полям интуитивно понятен: Чем занимается компилятор на самом деле.

Итак, как же компилятор позволяет вызывать метод с помощью стандартного синтаксиса объект. И откуда берется переменная value"! Чтобы ответить на эти вопросы, взглянем на MSIL-код, сгенерированный компилятором. Сначала рассмотрим метод-получатель свойства.

В следующем примере определен такой метод-получатель: Взглянув на MSIL, получившийся из этого метода, вы увидите, что компилятор создал метод-аксессор getJZipCode, как показано ниже: Однако в этом случае код не будет скомпилирован, так как явно вызывать внутренний метод MSIL недопустимо.

Ответ на наш вопрос — как компилятор позволяет использовать стандартный синтаксис объект. А теперь посмотрим на сгенерированный метод-установщик. В классе Address вы видели следующее: В этом коде не объявлена переменная value, но мы все же можем использовать ее для хранения значения, переданного вызывающим кодом, и для установки защищенного поля zipCode. В сгенерированном MSIL этот метод принимает как аргумент строковую переменную: Даже если вы не найдете этого метода в исходном коде на С , при установке свойства ZipCode [например, так: Как и в случае метода getJZipCode, попытка прямого вызова этого метода на С приводит к ошибке.

В нашем примере свойство Address. ZipCode считается доступным для чтения и записи, так как определены оба метода: Конечно, иногда может потребоваться лишить клиент возможности устанавливать значение данного поля. В этом случае вы можете сделать это поле неизменяемым, опустив метод-установщик. Чтобы проиллюстрировать неизменяемые свойства, предотвратим установку поля Address. ZipCode как единственную ветвь кода, задачей которого является изменение значение поля: У свойств, как и методов, могут быть указаны модификаторы virtual, override или abstract, о которых я рассказывал в главе 6.

Это позволяет производным классам наследовать и подменять свойства подобно любому другому члену, унаследованному от базового класса. Главная проблема в том, что вы можете задавать эти модификаторы только на уровне свойства. Иначе говоря, когда у вас есть оба метода — получатель и установщик, при подмене одного из них нужно подменять и второй.

Дополнительные возможности использования свойств. Третий пункт связан с еще одним полезным способом применения свойств — реализации отложенной инициализации lazy initialization. При этой методике оптимизации некоторые члены класса не инициализируются, пока не потребуются. Отложенная инициализация дает преимущества, если у вас есть класс с членами, на которые редко ссылаются и на инициализацию которых уходит много времени и ресурсов.

Примерами этого могут служить ситуации, когда требуется считывание данных из БД или через перегруженную сеть. Поскольку вам известно, что на эти члены ссылаются редко, а их инициализация требует больших ресурсов, их инициализацию можно отложить до вызова их методов-получателей.

Чтобы проиллюстрировать этот момент, допустим, что у вас есть приложение управления запасами, которое представители по продажам запускают на своих портативных компьютерах для размещения заказов клиентов, и время от времени используют его для проверки наличия товара.

Используя свойства, вы можете разрешить создание экземпляров соответствующих классов, так чтобы при этом не считывались записи из БД, как показано в приведенном ниже коде. Когда представитель захочет узнать о количестве товара на складе, метод-получатель обратится к удаленной БД. Итак, свойства позволяют предоставлять методы-аксессоры для полей и универсальные, интуитивно понятные интерфейсы для клиента.

Из-за этого свойства иногда называют "умными полями". А теперь рассмотрим способы определения и использования массивов на С. Вы также узнаете, как свойства используются с массивами в виде индексаторов indexers.

Visible

До сих пор мои примеры иллюстрировали способы определения конечного, предопределенного числа переменных. Однако во многих реальных приложениях точное число нужных объектов неизвестно до периода выполнения. Так, если вы разрабатываете редактор и хотите отслеживать число элементов управления, добавляемых к диалоговому окну, точное количество элементов управления, которое будет показано редактором, неизвестно до периода выполнения.

Но для хранения и отслеживания совокупности динамически выделяемых объектов, в данном случае — элементов управления редактора — вы можете использовать массив. В С массивы являются объектами, производными от базового класса System. Это значит, что члены каждого объявленного массива унаследованы от Sys-tem. В этом разделе я расскажу, как объявлять массивы и создавать их экземпляры, как работать с массивами разных типов, и опишу циклическую обработку элементов массива.

Я также коснусь нескольких распространенных свойств и методов класса System. Для объявления массива на С нужно поместить пустые квадратные скобки между именем типа и переменной, например, так: Поскольку массивы основаны на классах, многие из правил объявления классов применяются и к массивам. Например, при объявлении массива на самом деле вы не создаете его. Так же, как и в случае класса, вы должны создать экземпляр массива, и только после этого он будет существовать в том смысле, что для его элементов будет выделена память.

Вот как объявить массив и одновременно создать его экземпляр: Однако, объявляя массив как член класса, вам нужно разбить определение массива и создание его экземпляра на два четко обозначенных этапа, поскольку вы не можете создавать экземпляр объекта до периода выполнения: Вот простой пример объявления одномерного массива как члена класса. При этом в конструкторе создается и заполняется экземпляр массива, после чего все элементы массива выводит цикл.

В этом примере метод SingleDimArray. PrintArray определяет число элементов массива с помощью свойства Length класса System. Это не совсем наглядный пример, так как мы используем всего лишь одномерный массив, а свойство Length на самом деле возвращает число всех элементов по всем измерениям массива. Так, в случае двумерного массива 5 на 4 свойство Length вернет Ниже я рассмотрю многомерные массивы и способы определения верхней границы конкретного измерения массива.

Кроме одномерных, С поддерживает объявление многомерных массивов, где каждое измерение отделяется запятой. Здесь я объявил трехмерный массив двойных слов: Чтобы быстро определить число измерений массива, объявленного на С , подсчитайте число запятых и к сумме прибавьте единицу. В следующем примере я объявил двумерный массив объемов продаж, представляющих объемы продаж по месяцам в этом году и суммы за аналогичный период времени прошлого года.

Обратите особое внимание на синтаксис создания экземпляра массива в конструкторе MultiDimAirayApp. Для определения длины или верхней границы каждого измерения массива в методе MultiDimArray. PrintSales я использовал метод Array.

Свойство компонентов Parent

Далее я смог задействовать каждое конкретное значение в методе PrintSales. Теперь, увидев, что динамическая обработка одно- или многомерного массива большой сложности не представляет, вас может заинтересовать способ программного определения числа измерений массива. Число измерений массива называется рангом, а его значение позволяет получить свойство Array.

Вот как это сделать для нескольких массивов: Последнее, что мы рассмотрим в связи с массивами, — невыровненные массивы jagged array. Невыровненный массив — это просто массив массивов. Вот пример определения массива, состоящего из массивов целочисленных значений: Невыровненные массивы можно применять при разработке редактора. При этом вы можете хранить каждый объект, представляющий созданный пользователем элемент управления, в массиве.

Допустим, у вас есть массив кнопок и массив полей со списком чтобы этот пример был небольшим и легко управляемым. У вас могут быть три кнопки и три поля со списком в соответствующих массивах.

Объявив невыровненный массив, можно создать для этих массивов "родительский" массив, что позволит вам при необходимости легко выполнять циклическую программную обработку элементов управления: Как видите, я определил базовый класс Control , два производных Button и Combo и объявил массив массивов, содержащих объекты Controls. Таким образом, я могу хранить в массивах значения определенных типов и благодаря полиморфизму быть уверенным, что, когда наступит время извлечь объект из массива с помощью объектов, приведенных к базовому классу , все будет работать так, как я задумал.

Работа с объектами как с массивами с помощью индексаторов. Теперь вы знаете, как объявлять массивы и создавать их экземпляры, как работать с массивами разных типов и циклически обрабатывать элементы массивов. Вы также узнали, как для массивов использовать наиболее популярные свойства и методы, определенные в классе System. Теперь перейдем к рассмотрению индексаторов — особой возможности С , позволяющей программно обращаться с объектами так, как если бы они были массивами.

Но зачем это нужно? Как и в случае большинства функций языка программирования, польза от индексаторов в том, что писать приложения становится более интуитивно понятно. В разделе "Свойства как "умные поля"" вы узнали, как свойства в С дают вам возможность ссылаться на поля класса с использованием стандартного синтаксиса класс. Такие поля в конечном счете приводятся к методам-получателям и установщикам. Это абстрагирование освобождает программиста, пишущего клиент класса, от необходимости определения наличия у поля методов-получателей и установщиков и от необходимости знать их точный формат.

Аналогично индексаторы позволяют клиенту класса индексировать объект, как если бы объект был массивом. У вас есть класс "окно со списком", куда пользователь класса может вставлять строки. Когда этот механизм появился в конце х годов, мы думали, что были настоящими объектно-ориентированными программистами.

Разве после всего этого мы не посылали сообщения объекту, как нас учили все эти модные книги по объектно-ориентированному анализу и проектированию? В случае класса CListBox т. Приняв это во внимание и стремясь облегчить создание лучшего и наиболее интуитивно понятного языка, команда разработчиков С задалась вопросом: Вот из этой идеи и родилась концепция индексаторов.

Свойства иногда называются "умными полями", а индексаторы — "умными массивами", а значит, стоит использовать для них один синтаксис. Действительно, определение индексатора во многом напоминает определение свойств, кроме двух крупных отличий. Во-первых, индексатор принимает аргумент индекс. Во-вторых, поскольку сам класс применяется как массив, в качестве имени индексатора используется ключевое слово this.

Вскоре вы увидите более полный пример, а сейчас взгляните на такой пример индексатора: Это лишь часть примера, иллюстрирующего синтаксис индексаторов, так как внутренняя реализация способа определения данных, их получения и установки к индексаторам не относится. Имейте в виду, что независимо от внутреннего способа хранения ваших данных т. Что именно вы делаете в пределах индексатора — ваше личное дело, пока клиент класса получает при обращении к объекту как к массиву ожидаемые результаты.

Когда же применение индексаторов наиболее оправданно? Начну с уже приведенного примера окна со списком. С концептуальной точки зрения, такое окно представляет собой просто список, или массив строк, подлежащих выводу. В следующем примере я объявил класс с именем MyListBox, содержащий индексатор для установки и получения строк через объект ArrayList класс Array List является классом. NET Framework, который используется для хранения совокупности объектов. В этом примере я реализовал проверку на ошибки, возникающие при выходе индекса за границы.

Формально это не связано с индексаторами, поскольку индексаторы связаны лишь со способом использования объекта как массива клиентом класса, и никак — с внутренним представлением данных. Однако при изучении функций нового языка это помогает понять не только их синтаксис, но и принципы практического использования.

Итак, в обоих методах индексатора получателе и установщике я проверял передаваемое значение индекса с помощью данных, хранимых членом класса ArrayList. Лично я выбрал бы генерацию исключений в тех случаях, когда переданное значение индекса не может быть использовано. Но это дело вкуса — ваша обработка ошибок может отличаться.

Важно дать знать клиенту о возникновении ошибки, когда передается неверный индекс. Индексаторы — пример того, как добавленная к языку командой разработчиков небольшая, но мощная функция помогает повысить производительность наших усилий по разработке. Однако, как и у любой функции любого языка, у индексаторов своя область применения. Их нужно использовать только там, где понятно, что с данным объектом можно обращаться, как с массивом. Рассмотрим приложение по подготовке счетов.

В нем, конечно, нужен класс Invoice, определяющий член-массив объектов InvoiceDetail. В таком случае пользователю будет совершенно понятно применение следующего синтаксиса при обращении к подробностям счетов: Однако этого не скажешь о попытке превращения всех членов InvoiceDetail в массив, доступ к которому будет осуществляться через индексатор. Как видите, первая строка гораздо понятнее, чем вторая: Истина в том, что не стоит делать что-то лишь потому, что это возможно.

Свойства в С состоят из объявления полей и методов-аксессоров. Свойства обеспечивают интеллектуальный доступ к полям класса, что освобождает программиста, занятого написанием клиента класса, от необходимости выяснять, был ли создан для поля класса метод-аксессор и если был, то как.

Массивы С могут быть одномерными, многомерными или невыровненными. В С с объектами можно обращаться как с массивами, применяя индексаторы.

Индексаторы позволяют программистам легко работать с множеством объектов одного типа. Главная Статьи Новости Файлы Исходники Опросы Форумы Хостинг Eng Архив Карта. Поиск среди 20 статей: Свойства, массивы и индексаторы ГЛАВА 7.

Карта сайта

54 55 56 57 58 59 60 61 62