Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Троелсен Э. -> "С# и платформа .NET. Библиотека программиста" -> 76

С# и платформа .NET. Библиотека программиста - Троелсен Э.

Троелсен Э. С# и платформа .NET. Библиотека программиста — СПб.: Питер, 2004. — 796 c.
ISBN 5-318-00750-3
Скачать (прямая ссылка): cplatforma2004.pdf
Предыдущая << 1 .. 70 71 72 73 74 75 < 76 > 77 78 79 80 81 82 .. 320 >> Следующая

Prnns any key to continue
-I
H I Ял
Рис. 3.15. Виртуальные методы замещать не обязательно
Если нам необходимо гарантировать, что каждый производный класс обязательно заместит метод Draw(), то мы должны объявить метод Draw() в базовом классе Shape абстрактным. Абстрактные методы в С# работают так же, как чистые виртуальные функции в C++ — для них даже не надо указывать реализацию по умолчанию:
// Каждая геометрическая фигура теперь ОБЯЗАНА самостоятельно определять
// метод DrawO
public abstract class Shape
{
II Метод DrawO теперь определен как абстрактный (обратите внимание
//на точку с запятой)
public abstract void DrawO;
public string PetName
{
get {return petNaine:} set {petNarae - value;)
}
)
Теперь мы обязаны определить метод DrawC) в классе Ci -'Се:
// Если мы не заместим в классе Circle абстрактный метод DrawQ, класс Circle будет // также считаться абстрактным и мы не сможем создавать объекты этого класса! public class Circle : Shape
{
public CircleO [}
public Circle(string name): base(name) {}
// Теперь метод DrawO придется замещать в любом производном негюсрепсіе.енно
// от Shape классе
public override void DrawC)
Console.WriteLine("Drawing {0} the Crlcle", PetName):
I
174 Глава 3 • и объектно-ориентированное программирование
Теперь мы можем воспользоваться полной мощью полиморфизма С#, когда конкретная реализация метода будет выбираться автоматически в зависимости от того, для объекта какого класса был вызван этот метод:
// Создаем массив объектов разных геометрических фигур
public static int Ma1n(str1ng[] args)
{
// Массив фигур
Shape[] s =(new HexagonO, new Hexagon ("Freda").
new Circlet); new Circlet"JoJo"));
//Прохожим с помощью цикла по всем элементам массива и прост нарисовать // каждый объект
for(int 1=0: і < s.Length; і++) s[i].DrawO;
І"
Результат выполнения программы представлен на рис. 3.16.
' D:\C5liarpBook\l.abs\Chapter 3,Slldpei .Ы...
Drawing NnName the Hexagon Drawing Freda the Hexagon Drauinu NnNrtme the Circle Drau inj/ JoJo the Circle Press any hey to continue 1
ЛІ
Рис. Абстрактные методы ДОЛЖНЫ быть замещены
Этот пример очень хорошо иллюстрирует суть полиморфизма. Как мы помним, объекты абстрактных классов создавать невозможно. Однако вы вполне можете хранить ссылки на любой производный класс, используя для этого переменную абстрактного класса. В нашем примере при прохождении по элементам массива геометрических фигур нужный вариант метода выбирается непосредственно в момент выполнения программы в зависимости от класса, к которому принадлежит
объект.
Контроль версий членов класса
В существует еще один прием работы с методами в производных классах, который можно противопоставить замещению методов. Этот прием называется сокрытием методов (method hiding). Рассмотрим его на примере.
Предположим, что вы создаете новый класс с именем Oval (для новой геометрической фигуры нашей иерархии - овала). Пусть у нас Oval является производным классом от класса Circle. Тогда наша иерархия геометрических фигур будет выглядеть так, как показано на рис. 3.17.
Теперь предположим, что в классе Oval также определен метод Craw;). Однако представим, что, в отличие от отношений между реализациями метода Draw() в базовом классе, мы хотим запретить любое наследование логики Draw(} между методами — фактически разорвать отношения наследования на уровне единственного метода. С# предлагает для этого случая средст ю, которое называется контролем
Поддержка полиморфизма в С# 175
версий (versioning). Для того чтобы им воспользоваться, достаточно определить в классе . . метод DrawO с ключеным словом new:
// Класс Oval наследует классу Circle, однако сокрывает унаследованный метод DrawO
public class Oval : Circle
{
public OvalC) {base.PetName = "Joe":}
// Скрываем любые реализации DrawO базовых классов public new void DrawO
(
Il Специфичный для Oval алгоритм DrawO
)
J
Object
Здесь определен абстрактный метод DrawQ
Здесь определены методы Draw()
Oval
Полностью новый метод Diawi) скрывает метод Circle.Draw()
Рис. 3.17. Для метода DrawQ класса Oval мы применяем возможности контроля
версий членов класса
Поскольку в классе Ova 1 для метода) у нас использовано ключевое слон.) new, мы гарантируем, что при создании объекта класса Oval и вызове для него метода Draw! ) будет вызвана именно та реализация этого метода, которая определи -на в классе Oval. Ключевое слово new разрывает отношения между абстрактным методом Draw(), определенным в базовом классе Shape, и методом Draw() в классе Oval.
// Будет вызван метод DrawO. определенный в классе Oval Oval о = new Oval О: о. DrawO;
Однако если вам все же потребуется вызвать вариант метода для базового кгж -са, это тоже можно сделать — с помощыо явного приведения типов:
// Будет вызван нетод DrawO, определенный в классе Circle Oval о = new Oval О:
((Circle)o).DrawO; Il Приводим о к базовоиу классу
На этом примере можно убедиться, что сокрытие методов — это не просто интересное упражнение при проектировании классов, но достаточно полезное средство, часто используемое в реальных проектах. Особенно часто оно применяется в тех ситуациях, когда вам необходимо произвести класс от базового класса, ощх: -деленного в другой сборке .NET. Предположим, что в базовом классе у нас опреде-
Предыдущая << 1 .. 70 71 72 73 74 75 < 76 > 77 78 79 80 81 82 .. 320 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100