Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:
void Ргор3 ;
}
public interface IPropsOne
{
void Prop1(string s);
void Prop2 (int val);
void Ргор3 ;
}
У двух интерфейсов — по три метода с совпадающими именами, сигнатуры двух методов совпадают, а в одном случае различаются. Вот класс, наследующий оба интерфейса:
public class ClainTwo: IProps,IPropsOne
{
/// <summary>
/// склеивание методов двух интерфейсов
/// </summary>
/// <param name="s"></param>
public void Prop1 (string s)
{
Console.WriteLine (s);
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <param name="x"></param>
public void Prop2(string s, int x)
{
Console.WriteLine(s +"; " + x);
}
public void Prop2 (int x)
{
Console.WriteLine(x);
}
/// <summary>
/// переименование методов двух интерфейсов
/// </summary> void IProps.Ргор3
{
Console.WriteLine("Свойство 3 интерфейса 1");
}
void IPropsOne.Ргор3
{
Console.WriteLine("Свойство 3 интерфейса 2");
}
public void Prop3FromInterface 1
{
((IProps)this). Ргор3;
}
public void Prop3FromInterface2
{
((IPropsOne)this). Ргор3;
}
}
Для первого из методов с совпадающей сигнатурой выбрана стратегия склеивания, так что в классе есть только один метод, реализующий методы двух интерфейсов. Методы с разной сигнатурой реализованы двумя перегруженными методами класса. Для следующей пары методов с совпадающей сигнатурой выбрана стратегия переименования. Методы интерфейсов реализованы как закрытые методы, а затем в классе объявлены два новых метода с разными именами, являющиеся обертками закрытых методов класса.
Приведу пример работы с объектами класса и интерфейсными объектами:
public void TestCliTwoInterfaces
{
Console.WriteLine("Объект ClainTwo вызывает методы двух интерфейсов!");
Cli.ClainTwo claintwo = new Cli.ClainTwo ;
claintwo.Prop1("Склейка свойства двух интерфейсов");
claintwo.Ргор2("перегрузка::: ",99);
claintwo.Prop2(9999);
claintwo.Prop3FromInterface1 ;
claintwo.Prop3FromInterface2 ;
Console.WriteLine("Интерфейсный объект вызывает методы 1-го интерфейса!");
Cli.IProps ip1 = (Cli.IProps)claintwo;
ip1.Prop1("интерфейс IProps: свойство 1");
ip2.Prop2("интерфейс 1", 88);
ip1.Ргор3 ;
Console.WriteLine("Интерфейсный объект вызывает методы 2-го интерфейса!");
Cli.IPropsOne ip2 = (Cli.IPropsOne)claintwo;
ip2.Propl("интерфейс IPropsOne: свойство1");
ip2.Prop2 (7777);
ip2.Ргор3 ;
}
Результаты работы тестирующей процедуры показаны на рис. 19.2.
Рис. 19.2. Решение проблемы коллизии имен Наследование от общего предка
Проблема наследования от общего предка характерна, в первую очередь, для множественного наследования
Для интерфейсов сама ситуация дублирующего наследования маловероятна, но возможна, поскольку интерфейс, как и любой класс, может быть наследником другого интерфейса. Поскольку у интерфейсов наследуются только сигнатуры, а не реализации, как в случае классов, то проблема дублирующего наследования сводится к проблеме коллизии имен. По-видимому, естественным решением этой проблемы в данной ситуации является склеивание, когда методам, пришедшим разными путями от одного родителя, будет соответствовать единая реализация.
Начнем наш пример с наследования интерфейсов:
public interface IParent
{
void ParentMethod;
}
public interface ISonl: IParent {
void SonlMethod;
}
public interface ISon2:IParent {
void Son2Method;
}
Два сыновних интерфейса наследуют метод своего родителя. А теперь рассмотрим класс, наследующий оба интерфейса– .
public class Pars: ISon1, ISon2
{
public void ParentMethod
{
Console.WriteLine("Это метод родителя!");
}
public void Son1Method
{
Console.WriteLine("Это метод старшего сына!");
}
public void Son2Method
{
Console.WriteLine("Это метод младшего сына!");
}
}//class Pars
Класс обязан реализовать метод ParentMethod, приходящий от обоих интерфейсов. Понимая, что речь идет о дублировании метода общего родителя — интерфейса IParent, лучшей стратегией реализации является склеивание методов в одной реализации, что и было сделано. Приведу тестирующую процедуру, где создается объект класса и три объекта интерфейсных классов, каждый из которых может вызывать только методы своего интерфейса:
public void TestlParsons
{
Console.WriteLine("Объект класса вызывает методы трех интерфейсов!");
Cli. Pars ct = new Cli.Pars;
ct.ParentMethod;
ct.Son1Method;
ct.Son2Method;
Console.WriteLine("Интерфейсный объект 1 вызывает свои методы!");
Cli.IParent ip = (IParent)ct;
ip.ParentMethod;
Console.WriteLine("Интерфейсный объект 2 вызывает свои методы!");
Cli.ISonl ipl = (ISon1)ct;
ip1.ParentMethod ;