Чтение онлайн

на главную

Жанры

Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:

public class ClainP: IProps

{

public ClainP{ }

void IProps.Propl(string s)

{

Console.WriteLine (s);

}

void IProps.Prop2(string name, int val)

{

Console.WriteLine("name = {0}, val ={1}", name, val);

}

}//class ClainP

Класс ClainP реализовал методы интерфейса IProps, но сделал их закрытыми и недоступными для вызова клиентов и наследников класса. Как же получить доступ к закрытым методам? Есть два способа решения этой

проблемы:

Обертывание. Создается открытый метод, являющийся оберткой закрытого метода.

Кастинг. Создается объект интерфейсного класса IProps, полученный преобразованием (кастингом) объекта исходного класса ClainP. Этому объекту доступны закрытые методы интерфейса.

В чем главное достоинство обертывания? Оно позволяет переименовывать методы интерфейса. Метод интерфейса со своим именем закрывается, а потом открывается под тем именем, которое класс выбрал для него. Вот пример обертывания закрытых методов в классе ClainP;

public void MyPropl(string s)

{

((IProps)this).Prop1 (s);

}

public void MyProp2(string s, int x)

{

((IProps)this).Prop2(s, x);

}

Как видите, методы переименованы и получили другие имена, под которыми они и будут известны клиентам класса. В обертке для вызова закрытого метода пришлось использовать кастинг, приведя объект this к интерфейсному классу IProps.

Преобразование к классу интерфейса

Создать объект класса интерфейса обычным путем с использованием конструктора и операции new нельзя. Тем не менее, можно объявить объект интерфейсного класса и связать его с настоящим объектом путем приведения (кастинга) объекта наследника к классу интерфейса. Это преобразование задается явно. Имея объект, можно вызывать методы интерфейса — даже если они закрыты в классе, для интерфейсных объектов они являются открытыми. Приведу соответствующий пример, в котором идет работа как с объектами классов Clain, ClainP, так и с объектами интерфейсного класса IProps;

public void TestClainlProps

{

Console.WriteLine("Объект класса Clain вызывает открытые методы!");

Clain clain = new Clain ;

clain.Prop1(" свойство 1 объекта");

clain.Prop2("Владимир", 44);

Console.WriteLine("Объект класса IProps вызывает открытые методы!");

IProps ip = (IProps)clain;

ip.Prop1("интерфейс: свойство");

ip.Prop2 ("интерфейс: свойство",77);

Console.WriteLine("Объект класса ClainP вызывает открытые методы!");

ClainP clainp = new ClainP ;

clainp.MyProp1(" свойство 1 объекта");

clainp.MyProp2("Владимир", 44);

Console.WriteLine("Объект класса IProps вызывает закрытые методы!");

IProps ipp = (IProps)clainp;

ipp.Prop1("интерфейс:

свойство");

ipp.Prop2 ("интерфейс: свойство",77);

}

Этот пример демонстрирует работу с классом, где все наследуемые методы интерфейса открыты, и с классом, закрывающим наследуемые методы интерфейса. Показано, как обертывание и кастинг позволяют добраться до закрытых методов класса. Результаты выполнения этой тестирующей процедуры приведены на рис. 19.1.

Рис. 19.1. Наследование интерфейса. Две стратегии

Проблемы множественного наследования

При множественном наследовании классов возникает ряд проблем. Они остаются и при множественном наследовании интерфейсов, хотя становятся проще. Рассмотрим две основные проблемы — коллизию имен и наследование от общего предка.

Коллизия имен

Проблема коллизии имен возникает, когда два или более интерфейса имеют методы с одинаковыми именами и сигнатурой. Сразу же заметим, что если имена методов совпадают, но сигнатуры разные, то это не приводит к конфликтам — при реализации у класса наследника просто появляются перегруженные методы. Но что следует делать классу-наследнику в тех случаях, когда сигнатуры методов совпадают? И здесь возможны лее стратегии — склеивание методов и переименование.

Стратегия склеивания применяется тогда, когда класс — наследник интерфейсов — полагает, что разные интерфейсы задают один и тот же метод, единая реализация которого и должна быть обеспечена наследником. В этом случае наследник строит единственную общедоступную реализацию, соответствующую методам всех интерфейсов, которые имеют единую сигнатуру.

Другая стратегия исходит из того, что, несмотря на единую сигнатуру, методы разных интерфейсов должны быть реализованы по-разному. В этом случае необходимо переименовать конфликтующие методы. Конечно, переименование можно сделать в самих интерфейсах, но это неправильный путь: наследники не должны требовать изменений своих родителей — они сами должны меняться. Переименование методов интерфейсов иногда невозможно чисто технически, если интерфейсы являются встроенными или поставляются сторонними фирмами. К счастью, мы знаем, как производить переименование метода интерфейса в самом классе наследника. Напомню, для этого достаточно реализовать методы разных интерфейсов как закрытые, а затем открыть их с переименованием.

Итак, коллизия имен при множественном наследовании интерфейсов хотя и возможна, но легко разрешается. Разработчик класса может выбрать любую из двух возможных стратегий, наиболее подходящую для данного конкретного случая. Приведу пример двух интерфейсов, имеющих методы с одинаковой сигнатурой, и класса — наследника этих интерфейсов, применяющего разные стратегии реализации для конфликтующих методов.

public interface IProps

{

void Prop1(string s);

void Prop2 (string name, int val);

Поделиться:
Популярные книги

Отмороженный

Гарцевич Евгений Александрович
1. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный

Падение Твердыни

Распопов Дмитрий Викторович
6. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Падение Твердыни

Все ведьмы – стервы, или Ректору больше (не) наливать

Цвик Катерина Александровна
1. Все ведьмы - стервы
Фантастика:
юмористическая фантастика
5.00
рейтинг книги
Все ведьмы – стервы, или Ректору больше (не) наливать

Мастер 2

Чащин Валерий
2. Мастер
Фантастика:
фэнтези
городское фэнтези
попаданцы
технофэнтези
4.50
рейтинг книги
Мастер 2

Proxy bellum

Ланцов Михаил Алексеевич
5. Фрунзе
Фантастика:
попаданцы
альтернативная история
4.25
рейтинг книги
Proxy bellum

Романов. Том 1 и Том 2

Кощеев Владимир
1. Романов
Фантастика:
фэнтези
попаданцы
альтернативная история
5.25
рейтинг книги
Романов. Том 1 и Том 2

Законы Рода. Том 2

Flow Ascold
2. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 2

Имя нам Легион. Том 1

Дорничев Дмитрий
1. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 1

Барон устанавливает правила

Ренгач Евгений
6. Закон сильного
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Барон устанавливает правила

Повелитель механического легиона. Том I

Лисицин Евгений
1. Повелитель механического легиона
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Повелитель механического легиона. Том I

Как я строил магическую империю

Зубов Константин
1. Как я строил магическую империю
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Как я строил магическую империю

(Не)свободные, или Фиктивная жена драконьего военачальника

Найт Алекс
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
(Не)свободные, или Фиктивная жена драконьего военачальника

Кодекс Охотника. Книга X

Винокуров Юрий
10. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
6.25
рейтинг книги
Кодекс Охотника. Книга X

На изломе чувств

Юнина Наталья
Любовные романы:
современные любовные романы
6.83
рейтинг книги
На изломе чувств