Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 61
Текст из файла (страница 61)
В начале класса напдейггау объявляются следующие закрьпые переменные экземпляра: // Закрытые данные. тпк() а; // ссылка на базовый массив тпг 1оиегэоопбт // наименьший индекс 1пк оррегВоопб; // наибольший индекс Переменная а служит для обращения к базовому массиву по ссылке. Память для него распределяется конструктором класса Напде)(ггау. Нижняя граница индексирования массива хранится в переменной 1оиегноппб, а верхняя граница — в переменной пРРегвоппб Далее объявляются автоматически реализуемые свойства ъепдг)т и Вггог. Глава )О.
Нндексаторы н свойства 313 // Автоматически реализуемое и доступное только дпя // чтения свойство Ьепдсп. риЫ1с гпс ЬепдсЬ ( дест рг1тасе вегт // Автоматически реализуемое и доступное только для // чтения свойство еггог. риЫгс Ьоо1 Еггог ( дест рггтасе вест ) Обратите внимание на то, что в обоих свойства аксессор вес обозначен как рггиаге. Как пояснялось выше, такое объявление автоматически реализуемого свойства, по существу, делает его доступным только для чтения. Ниже приведен конструктор класса НапдеАггау. // Построить массив по заданному размеру. риЫ1с Напдеаггау(гпс 1он, гпс Ыдп) ( ЫдЬ+Ю 11(ЫдЬ <= 1он) ( Сопво1е.ыгггевгпе("Неверные индексы" ); ЫдЬ = 1т //' создать дпя надекнопти минимально допустимый массив 1он = От ) а = пен 1пс[ЫОЬ вЂ” 1он)," Ьепдсп = Ьгдп — 1оты 1онегвоипс) 1он; иррегэоипт) = — Ь1дпт ) При конструировании объекту класса напдедггау передается нижняя граница массива в качестве параметра 1ои, а верхняя граница — в качестве параметра ЬйдЬ.
Затем значение параметра Ь1дЬ инкрементируется,'поскольку пределы индексирования массива изменяются от 1он до Ь1дЬ включительно. Далее выполняется следующая проверка: является ли верхний индекс больше нижнего индекса. Если это не так, то выдается сообщение об ошибке и создается массив, состоящий из одного элемента. После этого для массива распределяется память, а ссылка на нее присваивается переменной а.
Затем свойство ЬепдСЬ устанавливается равным числу элементов массива. И наконец, устанавливаются переменные 1оиегВоип<[ и иррегВоипт). Далее в классе Напдедггау реализуется его индексатор, как показано ниже. // Это индексатор для класса Напдеаггау. риЫго гпс ГЫв[1пс Ьпоех] ( О Это аксессор дег. дег ( га(оК(гпсех)) ( Еггог = Га1вет гесигп а[1пк)ех — 1онегвоипс)т ) е1ве ( Еггог = Ггиет гесигп 0) // Это аксессор вес.
вег ( 314 Часть ), Язык С» 11 (ок (1пс(ех) ) ( а(хппех - 1онегвоцпк)) = ча1цет Еггог = Га1ае; ) е1ве еггог = сгцет ) ) Этот иидексатор подобен тому, что использовался в классе ра11Воусдггау, за одним существенным исключением. Обратите внимание иа следующее выражение, в котором индексируется массив а: апбех — 1оиегвоцпт( В зтом выражении индекс, передаваемый в качестве параметра 1пс)ех,преобразуется в индекс с отсчетом от нуля, пригодный для индексирования массива а. Данное выражение действует при любом значении переменной 1оыегВоцпсй положительном, отрицательном или нулевом.
Ниже приведен метод о)к () . // Возвратить логическое значение сгце, если О инлекс нахолится в установленных границах. ргхчаке Ьоо1 ок(1пв »ппех) ( 1Е(»ппех >= 1оиегвоцпк( а аппех <= цррегВоцпк() гекцгп Сгцет геьогп Га1ает ) Этот метод аналогичен использовавшемуся в классе Га11ВогсАггау, за исключеиием того, что в ием контроль границ массива осуществляется по значениям переменных 1оиегВоцпс) и цррегпоцпс). Класс ВапдеАггау демонстрирует лишь одну разновидность специализированного массива, который может быть создан с помощью иидексаторов и свойств.
Существуют, конечно, и другие. Аналогичным образом можно, например, создать динамические массивы, которые расширяются или сужаются по мере надобности, ассоциативные и разреженные массивы. Попробуйте создать один из таких массивов в качестве упражнения. ГЛАВА Наследование Н аследование является одним из трех основополагающих принципов объектноориентированного программирования, поскольку оно допускает создание иерархических классификаций. Благодаря наследованию можно создать общий класс, в котором определяются характерные особенности, присущие множеству связанных элементов.
От этого класса могут затем наследовать другие, более конкретные классы, добавляя в него свои индивидуальные особенности. В языке С№ класс, который наследуется, называется базовым, а класс, который наследует, — яроизводным. Следовательно, производный класс представляет собой специализированный вариант базового класса. Он наследует все переменные, методы, свойства и индексаторы, определяемые в базовом классе, добавляя к ним свои собственные элементы. Основы наследования Поддержка наследования в С№ состоит в том, что в объявление одного класса разрешается вводить другой класс.
Для этого при объявлении производного класса указывается базовый класс. Рассмотрим для начала простой пример. Ниже приведен класс тыопзьаре, содержащий ширину и высоту двухмерного объекта, например квадрата, прямоугольника, треугольника и т.д. // Клаас лля лвуыернык объектов. с1авв тновзьаре ( рньтвс боньге Нгбсь| рнЬ11с бонЬ1е Не1ЧЬС; рньъгс то1б ЯЬоивги() ( сопво1е.иг1сеь1пе("ширине и высота равны " т И1оЬЬ т " и " т НегЧЬС); ) ) Класс тнопзьаре может стать базовым, т.е, отправной точкой для создания классов, описывающих конкретные типы двумерных объектов.
Например, в приведенной ниже программе класс тнопЯЬвре служит для порождения производного класса тг1апо1е. Обратите особое внимание на объявление класса тгъапо1е. 316 Часть(. Язык Сз // Пример простой иерархии классов. пв1пд Яуапещз // Класс для двумерных объектов. с1аяв ТноРЯЬаре ( РпЫТс боиЫе Избппз рпЫТс бопЬ1е Нездпп," риЫ1с тотб ЯпонРТщ() ( сопво1е.игзгеьзпе("ширина и высота равны " + ИТНГП ь " и " + Не1дпс)з ) ) // Класс Тгзапд1е, производный от класса ТноОЯПаре.
с1ава Тгзапд1е: ТноРЯЬаре ( рпЫТс япгзпд 5Гу1е) // тип треугольника // Возвратить площадь треугольника. рпЬ11с бопЫе Игеа() ( гепьгп Иьбпп * Не10ЬГ / 2; // Показать тип треугольника. рпЫТс чо10 5пон5Гу1е() ( Сопво1е.игзсеЬТпе("Треугольник " + япу1е); ! ) с1авв Япарев ( вгагзс тозб Ма1п() ( Тгзапд1е Г1 пен Тгзапд1е() Тг1апд1е Г2 = пен Тгзапд1е() Г1.ИгбГП = 4.0) Г1.Нездпс 4.0) г1.5гу1е = "равнобедренный"; Г2.ИТНГЬ = 5.0) г2.Незднг = 12.0з Г2.5Гу1е = "прямоугольный"; Сопво1е.мгзпеРТпе("Сведения об объекте С1: "); Г1.5понЯГУ1е(); Г1.5понозв() з сопво1е.игзгеОтпе("площадь равна " ь г1.агеа())) Сопво1е.игзпеЬТпе() Сопао1е.игзпеОТпе("Сведения об объекте Г2: "); Г2.
ЯпонЯГУ1е (); Г2.5понОзщ() з Глава (). наследование 317 сопво1е.нгтгеь1пе ("площадь равна " + г2.Агеа() ) л ) ) При выполнении этой программы получается следующий результат; Сведения об объекте Г1: Треугольник равнобедренный Ширина и высота равны 4 и 4 Площадь равна 8 Сведения об объекте Г2: Треугольник прямоугольный Ширина и высота равны 8 и 12 Площадь равна 48 В классе тг1апп1е создается особый тип объекта класса тыоп5Ьаре (в данном случае — треугольник). Кроме того, в класс тгтапд1е входят все члены класса тыопзпаре, к которым, в частности, добавляются методы Агеа ( ) и зпоызг у1е ( ) . так, описание типа треугольника сохраняется в переменной зсу1е, метод Агеа () рассчитывает и возвращает площадь треугольника, а метод зноизсу1е () отображает тип треугольника. Обратите внимание на синтаксис, используемый в классе тгтапд1е для наследования класса Тыопзпаре: с1авв Тгтапд1е : Тыоозьаре ( Этот синтаксис может быть обобщен.
Всякий раз, когда один класс наследует от другого, после имени базового класса указывается имя производного класса, отделяемое двоеточием. В С() синтаксис наследования класса удивительно прост и удобен в использовании. В класс тг1апо1е входят все члены его базового класса тыопзпаре, и поэтому в нем переменные итбгп и негдпг доступны для метода Агеа () . Кроме того, объекты 81 и г2 в методе матп () могут обращаться непосредственно к переменным и14)гп и не1ппг, как будто они являются членами класса тггапп1е.
На рис. 11.1 схематически показано, каким образом класс Тыопзйаре вводится в класс Тгтапд1е. Тпапд)е Рмс. 1 1.1. Схематическое представление класса тгтапд1е несмотря на то что класс тыопзпаре является базовым для класса тгтапп1е, в то же время он представляет собой совершенно независимый и самодостаточный класс. Если класс служит базовым для производного класса, то это совсем не означает, что он не может быть использован самостоятельно.