2015-08-15 3 views
6

У меня есть два класса:Является ли класс, который наследует другой класс, наследует классы, наследуемые классы/интерфейсы?

public class Question : IDisposable, IEquatable<Question> 
{ 
} 

public class SessionQuestion : Question, IDisposable, IEquatable<SessionQuestion> 
{ 
} 

Как Question наследует IDisposable и IEquatable, делает SessionQuestion неявно наследуют эти интерфейсы, а?

+5

Да, это так ... – Amit

+0

Yup. Попробуйте сами: 'SessionQuestion s = new SessionQuestion();' then 'if (s is IDisposable)' – dman2306

+3

Внимание: не то, чтобы вы путались. Из-за наследования * SessionQuestion * наследует 'IEquatable ' from * Question *. Однако * SessionQuestion * также реализует 'IEquatable ', который представляет собой другой интерфейс, чем 'IEquatable '. Таким образом, вы можете опустить указание интерфейса * IDisposable * для * SessionQuestion * (он унаследован от * Question *), но вам нужно будет хранить 'IEquatable ' (так как этот интерфейс не реализован * Question *) – elgonzo

ответ

5

Ответ «Да» - интерфейсы наследуются. Однако, можете ли вы опустить, включая определения интерфейса из класса, зависит от того, хочет ли этот класс иметь определенные члены интерфейса как explicit interface implementations.

Давайте это очень простой (и глупо) пример:

public interface IMyInterface 
{ 
    void foo(); 
} 

public class A : IMyInterface 
{ 
    public void foo() 
    { 
     Console.Out.WriteLine("A.foo() executed"); 
    } 
} 

public class B : A, IMyInterface 
{ 
    void IMyInterface.foo() 
    { 
     Console.Out.WriteLine("B.foo() executed"); 
    } 
} 

Поскольку B хочет иметь Foo() метод как explicit interface implementation, то интерфейс IMyInterface должен быть указан как часть его определение класса - даже если класс A уже реализует этот интерфейс. В этом случае наследование декларации интерфейса из базового класса недостаточно.

Если класс B не имеет явных реализаций интерфейса, то классу B не нужно будет указывать интерфейс (IMyInterface в этом маленьком примере) снова.


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

Если выполнить следующую последовательность кода:

A obj = new A(); 
obj.foo(); 
IMyInterface x = obj; 
x.foo(); 

выход будет

A.foo() выполняется
А.Foo() выполняется


Однако давайте теперь использовать объект типа B, но в остальном сохранить код в точности то же самое:

B obj = new B(); 
obj.foo(); 
IMyInterface x = obj; 
x.foo(); 

выход будет несколько иным:

A.foo() выполнено
B.foo() выполнено

Почему это так? Помните, что класс B наследует реализацию метода foo() из класса A. Таким образом, вызов obj.foo() по-прежнему будет выполнять унаследованный метод foo().

Теперь, почему тогда x.foo() не вызывает foo() реализация, предоставляемая классом A? Или, почему obj.foo() не вызывает реализацию, заданную для foo() в классе B?

Поскольку х является переменным типа IMyInterface, таким образом, явная реализацией интерфейса Foo() метода, представленного объектом типа B имеет преимущество при вызове x.foo(). Переменная OBJ является не типа IMyInterface, следовательно, не будет obj.foo() ссылаться на явную реализацию интерфейса метода Foo().

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

+1

Техническим термином здесь является [Реализация интерфейса] (https://msdn.microsoft.com/en-us/library/aa664594.aspx).Менее путающей альтернативой этому может быть реализация интерфейса в базовом классе с помощью 'public' ***' virtual' *** method/property/etc. –

+0

@ JeppeStigNielsen, хорошая точка +1 – elgonzo

3

Конечно.

Фактически, .NET Framework вовсе не является иерархическим классом. Выберите случайный класс и посмотрите. Вы увидите, что он выводит класс, который получает класс, который ... и т. Д.

Интерфейсы также унаследованы великим детям, как и обычные классы.

И что касается членов, которые вы должны реализовать: если вы внедрили их в Question, вам не нужно их реализовывать в SessionQuestion, конечно.

3

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

Смежные вопросы