Программирование >>  Обработка исключительных ситуаций 

1 ... 64 65 66 [ 67 ] 68 69 70 ... 142


Работа с объектами через интерфейсы. Операции 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;

Однако если интерфейс реализуется с помощью виртуального метода класса, после его переопределения в потомке любой вариант обращения (через класс или через интерфейс) приведет к одному и тому же результату:



1 ... 64 65 66 [ 67 ] 68 69 70 ... 142

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика