Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Podbelsky_V_V_C_Bazovy_kurs.pdf
Скачиваний:
83
Добавлен:
02.06.2015
Размер:
1.73 Mб
Скачать

262

Г л а в а 1 3

 

 

Triangle tri = new Triangle(8.0, 4.0); tri.print();

tri.compress(0.25);

tri.print();

}

}

Результат выполнения программы:

Площадь прямоугольника=12,00. Габариты: dx=3,00, dy=4,00

Площадь треугольника=10,00. Габариты: dx=5,00, dy=4,00

Площадь треугольника=22,50. Габариты: dx=7,50, dy=6,00

Площадь треугольника=16,00. Габариты: dx=8,00, dy=4,00

Площадь треугольника=1,00. Габариты: dx=2,00, dy=1,00

В методе Main() определены две ссылки fig и tri. Первая имеет тип базового класса Figure и адресует вначале объект производного класса Rectangle, затем производного объект класса Triangle. Ссылка fig обеспечивает обращения к перегруженным методам print() производных классов Rectangle и Triangle. Ссылка tri может адресовать только объекты класса Rectangle и способна обеспечить вызов метода print() только этого же производного класса. В то же время для этой ссылки (и для ссылки fig) доступен метод сompress(). базового класса, унаследованный производными классами. Результаты выполнения программы иллюстрируют сказанное.

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

13.7. Опечатанные классы и методы

Кроме абстрактных методов и абстрактных классов, C# разрешает определять методы, свойства и классы, для которых

Включение, вложение и наследование классов

263

 

 

невозможно наследование. В объявление такого метода, свойства или класса входит модификатор sealed (опечатанный, герметизированный). Опечатанный класс нельзя использовать в качестве базового класса. Опечатанный метод и опечатанное свойство при наследовании нельзя переопределить.

В базовой библиотеке классов .NET Framework много опечатанных классов. Программисты, работающие с библиотекой в качестве пользователей, не могут создавать собственные производные классы на основе опечатанных классов .NET Framework. Таким опечатанным библиотечным классом является класс string.

13.8. Применение абстрактых классов

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

В качестве примера обратимся еще раз к абстрактному классу Figure и производным от него классам Rectangle и Triangle. В этих классах определены методы square(), возвращающие значения площадей объектов конкретных классов (не абстрактных). Следующий метод позволяет вывести значение любого объекта классов Triangle и Rectangle (программа 13_13.cs).

static void figSq(Figure f)

{ Console.WriteLine("Площадь = " + f.square()); }

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

static Figure figRec(Figure[] ar, int n) { return ar[n]; }

Параметры метода – ссылка на массив ссылок с типом Figure и целое n, определяющее индекс элемента этого массива. Возвращаемое значение метода – значение элемента массива. При обращении к методу в качестве аргумента используется ссылка на массив с типом элементов Figure. Каждому элементу

264

Г л а в а 1 3

 

 

массива–аргумента должно быть присвоено значение ссылки на объект конкретного класса, производного от Figure.

В следующем фрагменте программы 13_13.сs определен массив ссылок с типом Figure. Его элементам присвоены ссылки на объекты классов Rectangle и Triangle.

class Program

{

static void figSq(Figure f)

{ Console.WriteLine("Площадь = " + f.square()); } static Figure figRec(Figure[] ar, int n) { return ar[n]; } static void Main()

{

Figure[] arF = new Figure[4]; arF[0] = new Rectangle(3.0, 4.0); arF[1] = new Triangle(5.0, 4.0); Triangle tri = new Triangle(8.0, 4.0); arF[2] = tri;

Rectangle rec = new Rectangle(1.0, 3.0); arF[3] = rec;

for (int i = 0; i < arF.Length; i++)

{

Figure f = figRec(arF, i); figSq(f);

}

Console.WriteLine("Типы элементов массива: "); foreach (Figure g in arF)

Console.WriteLine(g.GetType());

}

}

Результат выполнения программы:

Площадь = 12 Площадь = 10 Площадь = 16 Площадь = 3

Типы элементов массива:

Rectangle

Triangle

Triangle

Rectangle

Включение, вложение и наследование классов

265

 

 

Впрограмме элементы массива arF обрабатываются в двух циклах. В цикле с заголовком for переменной Figure f присваиваются значения, возвращаемые методом figRec(). Затем f используется в качестве аргумента метода figSq(). Тем самым выводятся значения площадей всех фигур, “адресованных” элементами массива arF.

Вцикле с заголовком foreach перебираются все элементы массива arF и к каждому значению элемента, которое присвоено переменной Figure g, применяется метод GetType(). Результат

список названий классов, реализовавших абстрактный класс Figure.

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

Контрольные вопросы

1.Объясните различие между агрегацией и композицией классов.

2.Какого типа параметр должен быть у конструктора класса, находящегося в отношении агрегации с включаемым классом?

3.Какие члены внешнего класса доступны для вложенного класса?

4.Какой статус доступа должен иметь вложенный класс, чтобы он был доступен там, где виден внешний класс?

5.Как обратиться к члену вложенного класса вне внешнего класса?

6.В чем отличия вложения классов от агрегации и композиции?

7.Сколько прямых базовых классов допустимо для производного класса?

8.Какова роль инициализатора конструктора в конструкторе производного класса?

9.Что такое спецификация базы класса?

10.Какие члены базового класса наследуются производным классом?

11.Объясните правила доступа к членам базового класса из методов производного класса.

12.Объясните правила доступа к членам базового класса для объектов производного класса.

13.Что такое защищенный член класса?

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]