Г. Шилдт - С#4.0 Полное руководство (1160795), страница 62
Текст из файла (страница 62)
Затем свойство ьепдгЬ устанавливается равным числу элементов массива. И наконец, устанавливаются переменные 1оыегВоппб и пррегВоппб. Далее в классе ВапдеАг га у реализуется Его ицдексатОр, как показано нижЕ. /! Это индексатор дпя класса КапдеАггау. рпЫЬс 1пс ГЫз (1пс ьпбех) ( Это аксессор дес. дес ( ЬГ(о)с(гпс(ех)) ( еггог = Га1вег геспгп а(1пбех — 1онегВоипб); е1ве ( Еггог = Ггпе) гегпгп Ог 328 Часть ). Язык С() Это аксессор яег. яео ( 1Г(ох(ьпоех)) а(ьпоех — 1онегвоцпо) = ча1це," Еггог = Га1яе) ) е1яе еггог = ггце! ) Этот индексатор подобен тому, что использовался в классе Ра11эоггйггау, за одним существенным исключением.
Обратите внимание на следующее выражение, в котором индексируется массив а. 1пг)ех — 1онегвоипс) В этом выражении индекс, передаваемый в качестве параметра 1пбех, преобразуется в индекс с отсчетом от нуля, пригодный для индексирования массива а. Данное выражение действует при любом значении переменной 1оиегноцпс): положительном, отрицательном или нулевом.
Ниже приведен метод о)г () . Возвратить логическое значение Ггце, если индекс находится в установленных границах. ргьчаге Ьоо1 о)ь(1пг 1пс)ех) ( 1Г(ьпеех >= 1онегвоцпо Ь ьпоех <= цррегвоцпо) гегцгп Сгце; гесцгп Га1яе; ) Этот метод аналогичен использовавшемуся в классе Га11зойгйггау, за исключением того, что в нем контроль границ массива осуществляется по значениям переменных 1онегВоцпс) и цррегноцпс).
Класс рапоейггау демонстрирует лишь одну разновидность специализированного массива, который может быть создан с помощью индексаторов и свойств. Существуют, конечно, и другие. Аналогичным образом можно, например, создать динамические массивы, которые расширяются или сужаются по мере надобности, ассоциативные и разреженные массивы. Попробуйте создать один из таких массивов в качестве упражнения. 330 Часть!. Язык С№ риЫТс бооЫе Не1оЬС4 рпЫТс чо1б БЬонокш() Сопяо1е.игксеькпе("ширина и высота равны " И1бСЬ т " и " + Нег№ЬС)) Класс ТноОЯЬаре может стать базовым, т.е.
отправной точкой для создания классов, описывающих конкретные типы двумерных объектов. Например, в приведенной ниже программе класс Тио ОБЬаре служит для порождения производного класса Т с1апо1е. Обратите особое внимание на объявление класса Тг1апо1е. // Пример простой иерархии классов. ояьпд Яуягеш4 Класс для двумерных объектов. с1аяя ТноОБЬаре ( рпЬ11с бопЫе И1бСЬ4 рпЫТс боиЫе Не10ЬС4 роЫ1с чо1б БЬон01ш() ( сопяо1е.игксеъкпе("ширина и высота равны " И1бСЬ + " И " + НЕ10ЬС)4 // Класс Тг1апд1е, производный от класса Тноозларе. с1аяя Тг1ап01е : ТноОБЬаре ( роЬ11с ятгтпц Бгу1е) // тип треугольника // Воэвратить площадь треугольника. роЬ11с бооЫе агеа() ( гетпгп И1бСЬ * НеТЧЬС / 2; ) // Показать тип треугольника. роЫТс чокб ЯЬонзту1е() ( Сопяо1е.нгаяеьтпе("Треугольник " Ь Яяу1е) ) ) с1аяя ЯЬарея ( втаятс чотб Матп() ( Тттапд1е С1 = пен Тгкапд1е(); ТГ1апд1е С2 = пен Тгкапд1е()) С1.И1бСЬ = 4.0) С1.НеТЧЬЬ = 4.0) Ы .Яоу1е = "равнобедренный"; С2.ИТНЬЬ = 8.0; С2.Не10ЬС = 12.04 С2.8яу1е = "прямоугольный"; сопяо1е.нгаоеъьпе("Сведения об объекте С1: Глава 11.
Наследование 331 С1.ЯПонзпу1е(); С1.ЯПонотщ() 4 Сопяо1е.кгтпещпе (" Площадь равна " + С1.лгеа () ); Сопяо1е.кгтпеьтпе() Сопяо1е.игтгеьтпе("Сведения об объекте С2: "); г2. Японзпу1е (); С2.ЯПонотщ()4 сопяо1е.нгтпеъьпе("Площадь равна " + С2.лгеа())) ) ) При выполнении этой программы получается следующий результат. Сведения об объекте Г1: Треугольник равнобедренный Ширина и высота равны 4 и 4 Площадь равна 8 Сведения об объекте П2: Треугольник прямоугольный Ширина и высота равны 8 и 12 Площадь равна 48 В классе тг1апо1е создается особый тип объекта класса тыоРБ)заре (в данном случае — треугольник). Кроме того, в класс Тг1апо1е входят все члены класса ТиоРБЛаре, к которым, в частности, добавляются методы Агеа () и Б)тоынгу1е () .
Так, описание типа треугольника сохраняется в переменной Бгу1е, метод Агеа () рассчитывает и возвращает площадь треугольника, а метод Б)зоынсу1е () отображает тип треугольника. Обратите внимание на синтаксис, используемый в классе Тгтапо1е для наследования класса ТноРБ)гере.
с1аяя Тгтап81е : тнобзьаре ( Этот синтаксис может быть обобщен. Всякий раз, когда один класс наследует от другого, после имени базового класса указывается имя производного класса, отделяемое двоеточием. В С)) синтаксис наследования класса удивительно прост и удобен в использовании. В класс тгтапо1е входят все члены его базового класса тыоРБ)таре, и поэтому в нем переменные Хтс(гп и Нето)з С доступны для метода А ге а ( ) . Кроме того, объекты С1 и 12 в методе Натп () могут обращаться непосредственно к переменным И1Ж)з и не1о)тс, как будто они являются членами класса Тгтапо1е. На рис.
11.1 схематически показано, каким образом класс ТмоРБПаре вводится в класс Тгтапо1е. Тн оРБ)щре Тпяпв)е Рис. 11.1. Схематическое представление класса тсдапд1е 332 Часть (. Язык С() Несмотря на то что класс ТыоРБЬаре является базовым для класса Тггапс1е, в то же время он представляет собой совершенно независимый и самодостаточный класс. Если класс служит базовым для производного класса, то это совсем не означает, что он не может быть использован самостоятельно.
Например, следующий фрагмент кода считается вполне допустимым. тноОБЬаре яЬаре = пен ТноОБЬаре(); япаре.нгбСЬ = 10; япаре.не1ЧЬС = 20; япаре.БЬонпгш() Разумеется, объект класса ТмоРБЬаре никак не связан с любым из классов, производных от класса ТноРБЬаре, и вообще не имеет к ним доступа. Ниже приведена общая форма объявления класса, наследующего от базового класса. с1аяя имя производного класса : имя базового класса ( тело класса ) Для любого производного класса можно указать только один базовый класс.
В С() не предусмотрено наследование нескольких базовых классов в одном производном классе. (В этом отношении С)) отличается от С++, где допускается наследование нескольких базовых классов. Данное обстоятельство следует принимать во внимание при переносе кода С++ в С)).) Тем не менее можно создать иерархию наследования, в которой производньгй класс становится базовым для другого производного класса.
(Разумеется, ни один из классов не может быть базовым для самого себя как непосредственно, так и косвенно.) Но в любом случае производный класс наследует все члены своего базового класса, в том числе переменные экземпляра, методы, свойства и индексаторы. Главное преимущество наследования заключается в следующем: как только будет создан базовый класс, в котором определены общие для множества обьектов атрибуты, он может быть использован для создания любого числа более конкретных производных классов.
А в кавсдом производном классе может быть точно выстроена своя собственная классификация. В качестве примера ниже приведен еще один класс, производный от класса ТмоРБЬаре и инкапсулирующий прямоугольники. Класс для прямоугольников, производный от класса ТноОБЬаре. с1аяя Несгап01е : тноОБЬаре ( // Возвратить логическое значение Ггсе, если // прямоугольник является квадратом.
рпЬ11с Ьоо1 1яБЧсаге() ( 11(игбсп == Не1БЬГ) гегсгп СгчеГ гегсгп Га1яег ) Возвратить площадь прямоугольника. риЬ11с босЬ1е Пгеа() ( гегигп Хгсвп * Немапш ) ) В класс Несгапс1е входят все члены класса ТиоРБЬаре, к которым добавлен метод 1 яБЧОа ге ( ), определяющий, является ли прямоугольник квадратом, а также метод йгеа (), вычисляющий площадь прямоугольника. Глава 11. Наследование 333 Аоступ кчленам класса и наследование Как пояснялось в главе 8, члены класса зачастую объявляются закрытыми, чтобы исключить их несанкционированное или незаконное использование.
Но наследование класса не отменяет ограничения, накладываемые на доступ к закрытым членам класса. Поэтому если в производный класс и входят все члены его базового класса, в нем все равно оказываются недоступными те члены базового класса, которые являются закрытыми. Так, если сделать закрытыми переменные класса ТХООБЬаре, они станут недоступными в классе Тг1апд1е, как показано ниже. // Доступ к закрытым членам класса не наследуется.
// этот пример кода не подлежит компиляции. ояьпэ Буясеш; Класс для двумерных объектов. с1аяя Тноэзпаре ( СоцЬ1е ХТОСЬ; // теперь зто закрытая переменная СооЬ1е Вегопщ // теперь зто закрытая переменная рцЫ1с уота Бпонрьш() ( Сопяо1е.иг1геъьпе(ГШирина и высота равны " Х1ссп + " и " + Иетопс); ) Класс Тгьап51е, производный от класса ТноО5Ьаре.
с1авя Тгтап51е : Тносзпаре рцЫ1с вггьпд Бгу1е; // тип треугольника // Возвратить площадь треугольника. рцЬ1тс боцЬ1е Агеа() ( гевцгп ХТСГЬ * Неьэпг / 2; // Ошибка, доступ к закрытому члену класса запрещен ) Показать тип треугольника. роЬ11с чогб Бпонзгу1е() ( Сопяо1е.игьсеъьпе("Треугольник " ь Бсу1е) ) ) Класс Тг1апд1е не будет компилироваться, потому что обращаться к переменным Х1г(СЬ и Не1дЬС из метода Агеа () запрещено.