|
Программирование >> Обработка исключительных ситуаций
Работа с объектами через интерфейсы. Операции is и as При работе с объектом через объект типа интерфейса бывает необходимо убедиться, что объект поддерживает данный интерфейс. Проверка выполняется с помощью бинарной операции is. Эта операция определяет, совместим ли текущий тип объекта, находящегося слева от ключевого слова is, с типом, заданным справа. Результат операции равен true, если объект можно преобразовать к заданному типу, и false в противном случае. Операция обычно используется в следующем контексте: 1f ( объект is тип ) { выполнить преобразование объекта к типу // выполнить действия с преобразованным объектом Допустим, мы оформили какие-то действия с объектами в виде метода с параметром типа object. Прежде чем использовать этот параметр внутри метода для обращения к методам, описанным в производных классах, требуется выполнить преобразование к производному классу. Для безопасного преобразования следует проверить, возможно ли оно, например так: static vod Act( object A ) { if ( A is lAction ) { lAction Actor = (lAction) A; Actor.Draw(); В метод Act можно передавать любые объекты, но на экран будут выведены только те, которые поддерживают интерфейс IAction. Недостатком использования операции is является то, что преобразование фактически выполняется дважды: при проверке и при собственно преобразовании. Более эффективной является другая операция - as. Она выполняет преобразование к заданному типу, а если это невозможно, формирует результат null, например: static void Act( object A ) lAction Actor = A as lAction; if ( Actor != null ) Actor.Draw(); Обе рассмотренные операции применяются как к интерфейсам, так и к классам. Метод F из интерфейса IBase скрыт интерфейсом ILeft, несмотря на то что в цепочке IDerived - IRight - IBase он не переопределялся. Класс, реализующий интерфейс, должен определять все его элементы, в том числе унаследованные. Если при этом явно указывается имя интерфейса, оно Естественно, интерфейс не может быть наследником самого себя. Интерфейсы и наследование Интерфейс может не иметь или иметь сколько угодно интерфейсов-предков, в последнем случае он наследует все элементы всех своих базовых интерфейсов, начиная с самого верхнего уровня. Базовые интерфейсы должны быть доступны в не меньшей степени, чем их потомки. Например, нельзя использовать интерфейс, описанный со спецификатором private или internal, в качестве базового для открытого (publ ic) интерфейса. Как и в обычной иерархии классов, базовые интерфейсы определяют общее поведение, а их потомки конкретизируют и дополняют его. В интерфейсе-потомке можно также указать элементы, переопределяющие унаследованные элементы с такой же сигнатурой. В этом случае перед элементом указывается ключевое слово new, как и в аналогичной ситуации в классах. С помощью этого слова соответствующий элемент базового интерфейса скрывается. Вот пример из документации С#: interface 1 Base i void F( int i ): interface I left : IBase { new void F( int i ); переопределение метода F interface Inght ; IBase void G(): interface Iderived : I Left, I Right {} class A void Test( IDerived d ) { d.F( 1 ); Вызывается I Left F ((IBase)d).F( 1 ): Вызтвается IBase.F ((ILeft )d). F( 1 ); Вызывается I Left. F v(IRight)d).F( 1 ); /7 Вызывается IBase.F должно ссылаться на тот интерфейс, в котором был описан соответствующий элемент, например: class А : IRight IRight.GO { ... } IBase.F( int i ) { ... } IRight.F( int i ) - нельзя Интерфейс, на собственные или унаследованные элементы которого имеется явная ссылка, должен быть указан в списке предков класса, например: class В : А IRight.GO { class С : A. IRight IRight.GO { ... } IBase.F( int i ) { ... } нельзя! II можно можно Класс наследует все методы своего предка, в том числе те, которые реализовывали интерфейсы. Он может переопределить эти методы с помощью спецификатора new, но обращаться к ним можно будет только через объект класса. Если использовать для обращения ссылку на интерфейс, вызывается не переопределенная версия: interface IBase void АО: class Base : IBase public void AO { class Derived: Base new public void AO { Derived d d.AO; IBase id = d; id.AO; new Derived () ; вызывается Derived.AO; вызывается Base.AO; Однако если интерфейс реализуется с помощью виртуального метода класса, после его переопределения в потомке любой вариант обращения (через класс или через интерфейс) приведет к одному и тому же результату:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |