logo
C#, 320 стр

Наследование от общего предка

Проблема наследования от общего предка характерна, в первую очередь, для множественного наследования классов. Если класс C является наследником классов A и B, а те, в свой черед, являются наследниками класса Parent, то класс наследует свойства и методы своего предка Parent дважды, один раз получая их от класса A, другой от - B. Это явление называется еще дублирующим наследованием. Для классов ситуация осложняется тем, что классы A и B могли по-разному переопределить методы родителя и для потомков предстоит сложный выбор реализации.

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

Начнем наш пример с наследования интерфейсов:

public interface IParent

{

void ParentMethod();

}

public interface ISon1:IParent

{

void Son1Method();

}

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 TestIParsons()

{

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.ISon1 ip1 = (ISon1)ct;

ip1.ParentMethod();

ip1.Son1Method();

Console.WriteLine("Интерфейсный объект 3 вызывает свои

методы!");

Cli.ISon2 ip2 = (ISon2)ct;

ip2.ParentMethod();

ip2.Son2Method();

}

Результаты работы тестирующей процедуры показаны на рис. 19.3.

Рис. 19.3.  Дублирующее наследование интерфейсов