继承:内部类与内部接口

时间:2018-10-16 20:36:20

标签: c# inheritance

在表达对preventing exposure of base classes的关注的同时,我(通过测试)得知public类不能从internal类继承;但是,public类可以从internal接口继承。我真的很好奇为什么这是可能的。我认为这可能是由于以下原因之一(或其任意组合):

  1. 接口仅包含必须实现的签名。
  2. 一个类可能具有可以通过派生类型访问的属性,方法等。
  3. 类可能具有可以被派生类型覆盖的方法。

案例1

我相信,由于接口只是包含签名的 contract ,并且声明派生类型必须实现这些签名,因此允许继承。这是由于这样的事实,即接口并不关心谁访问这些签名,而只是在派生类型实现它们。


情况2和3

interfaces不同,类可以具有public属性,可以通过派生类型进行访问。例如:

private class A {
    public int SomeProperty { get; set; } = 0;
}
public class B : A {
    // Some cool code.
}
public class C : B {
    public int MyInt => SomeProperty;
}

由于SomePropertypublic,因此该结构的可访问性不一致,并且所有派生类型都可以访问该结构;因此AB必须具有相同的访问级别,以防止暴露。


这是为什么public类可以从internal interface派生而不能从internal class派生的原因,还是我错过了什么吗?另外,还有其他原因使之成为可能吗?


注意

我不是在寻找基于意见的答案;我正在寻找实现这一目标的技术上正确的原因。

这不是重复的,因为我想知道为什么不能从一个衍生而来的原因。

1 个答案:

答案 0 :(得分:1)

我认为您缺少的关键概念是继承和接口实现之间的区别。

当一个类继承另一个类时,这意味着它基本上是基类的一种更特定的类型-例如,狗是动物的一种特定类型,因此当您拥有这样的类时:

class Animal {/* implementation here */}
class Dog : Animal {/* dog implementation here */}

Dog类已经包含了Animal的所有实现,除了它的构造函数(静态和实例)和终结器。

但是,当一个类实现一个接口时,意味着它必须提供该接口的成员(即方法,属性,事件和索引器),因此,如果您有一个IAnimal接口和一个{{1 }}类直接实现它,您的代码如下所示:

Dog

请注意,interface IAnimal { void Eat(); } class Dog : IAnimal { public void Eat() {/* implementation here */} } 声明的所有内容都必须在IAnimal类中显式或隐式实现-因此,接口提供的协定将保留在该类中-无论用户是否使用类的人是否知道接口。

因此,总而言之-要使用该类,您无需了解其实现的接口的任何信息,但是您确实需要知道该类的所有内容,并且由于Dog是动物,因此如果Dog是公共的,动物也必须如此。
另一方面,IAnimal界面可以保留在内部。

关于实现内部接口的另一点,已经在user2864740的问题注释中提到-由于所有隐式接口实现都必须是公共的-如果要实现内部接口,则应考虑使用implementing it explicitly-该实现保留在内部,并且不会在包含的程序集之外公开。