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

 

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

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

Троелсен Э. С# и платформа .NET. Библиотека программиста — СПб.: Питер, 2004. — 796 c.
ISBN 5-318-00750-3
Скачать (прямая ссылка): cplatforma2004.pdf
Предыдущая << 1 .. 80 81 82 83 84 85 < 86 > 87 88 89 90 91 92 .. 320 >> Следующая

К этому моменту у вас мог созреть один интересный вопрос. Как мы уже выяснили, интерфейс — это набор абстрактных членов. Однако С# позволяет нам использовать абстрактные члены и в обычном классе. Так зачем же вообще нужны интерфейсы, если мы можем создать набор абстрактных методов, реализовав его
как класс, и сделать этот класс базовым для наших пользовательских классов? Ответ будет прост: класс — это класс, а интерфейс — это интерфейс. В классах помимо абстрактных методов, свойств и событий определяются также переменные класса и обычные (не абстрактные) методы, появление которых в интерфейсе исключено.
Интерфейс — это чистая синтаксическая конструкция, которая предназначена только для определенных целей. Интерфейсы никогда не являются типами дан-
Программирование с использованием интерфейсов 199
пых, и в них не бывает реализаций методов по умолчанию. Каждый член интерфейса (будь то свойство или метод) автоматически становится абстрактным. Кроме того, вспомним, что в С# (и во всем мире .NET) наследование одного класса более чем от одного базового класса (то есть множественное наследование) запрещено. В то же время реализация в классе сразу нескольких интерфейсов — это
обычное дело.
Реализация интерфейса
Когда в С# какой-либо класс должен реализовать нужные нам интерфейсы, названия этих интерфейсов должны быть помещены (через запятую) после двоеточия,, следующего за именем этого класса. Обратите внимание, что имя базового класса всегда должно стоять перед именами любых интерфейсов:
// Любой класс может реолчэоаывать любое количество интерфейсов, но он должен
// производиться только от одного базового класса:
public class Hexagon : Shape. IPointy г
public Hexagon(){}
public Hexagon(string name): base(name)(}
public override void DrawC) f
// Вспоннин, что в классе Shape определено свойство PetName Console.WriteLineC'Drawing {0} the Hexagon", PetName):
)
//Реализация IPointy
public byte GetNumberOfPointsO
i
return 6;
)
}
public class Triangle : Shape. IPointy {
public TriangleOO
public Triangle(string name) : base(name) {}
public override void
(
Console.WriteLineC'Drawing <Q) the Triangle". PetName):
}
// Реализация IPointy
public byte GetNumberOfPointsO
(
return 3;
Теперь и Hexagon, и Triangle, когда их об этом попросят, предоставят информацию о том, сколько у них углов. Обратите внимание, что вы не можете выбирать, какие методы в интерфейсе вам реализовывать, а какие - нет. В классе либо должны быть реализованы все методы данного интерфейса, либо этот интерфейс вообще не реализуется — половинчатого решения быть не может.
200 Глава 4 • Интерфейсы и коллекции
Чтобы легче было представить настоящее состояние нашей иерархии геометрических фигур, обратимся к рис. 4.1. Программистам, работавшим с СОМ, будет, без сомнения, хорошо знаком такой «леденцовый» (lollipop) способ отображения иерархии классов и поддерживаемых этими классами интерфейсов. Для них же (программистов, пришедших из мира СОМ) отметим, что классы Hexagon и Tri angle нереализуют интерфейс IUnknown и производятся от общего базового класса.
Object
Shape
Hexagon
Circle
Triangle
I Pointy
O 'Pointy
Рис. 4.1. Иерархия геометрических фигур с интерфейсами
Получение ссылки на интерфейс
С# позволяет обращаться к членам интерфейсов несколькими способами. Предположим, что мы создаем объект одного из наших классов и нам необходимо вызвать для него метод GetNumberOfPointsO, входящий в наш интерфейс IPointy. Первый способ — воспользоваться явным приведением типов:
// Получаем ссылку на интерфейс IPointy. используя явное приведение типов
Hexagon hex = new Hexagon("Bill"):
IPointy itfPt - (IPointy)hex;
Consol e. WriteLineCi-tfPt .GetNumberOf Poi ntSO):
Здесь мы получаем ссылку на интерфейс IPointy, явно приводя объект класса Hexagon ктипу IPointy. Если класс Hexagon поддерживает интерфейс IPointy, мы получим ссылку на интерфейс (у нас она называется itfPt) и все будет хорошо. Однако что произойдет, если мы попробуем применить то же самое приведение типов к объекту класса, не поддерживающего IPointy (например, класса Circle)? Результат будет неутешителен: мы получим сообщение об ошибке времени выполнения (рис. 4.2). Когда мы пытаемся получить ссылку на интерфейс путем явного приведения типов для объекта класса, не поддерживающего данный интерфейс, система генерирует исключение Inval idCastExceptHcn.
Программирование с использованием интерфейсов 201
Чтобы избежать проблем с исключением, исключение нужно перехватить:
// Используя поотоаимные средства, поэтапно перехватываем кскпеченче Circle с - new CircleC'Lisa");
IPointy itfPt; try
і
itfPt = (IPointy)c:
Consol е .Wri teLinedtf Pt. GetNuraberOfPoi nts()):
catchtlnvalidCastException е)
{ Console.WriteLineCOOPS! Not pointy..."): }
: ¦ D:\C5barpBook\Labs\Chapter 4\SMpes\bin\Debug\Shap.. вЯрІВ
Exception oceui-i-ed: System. InoalidCastExcept ion
at Shapes . ShapesApp. Ma in (Sy:; t en . S t t-i ng I 1 > Pres: any bey to continue
Рис. 4.2. Ошибка при приведении типов
Предыдущая << 1 .. 80 81 82 83 84 85 < 86 > 87 88 89 90 91 92 .. 320 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100