我刚刚在.net中遇到了关于继承的基本规则:
CS0060:类类型的直接基类必须至少与类类型本身一样可访问
我很好奇为什么要制定这个规则。
有人知道为什么这种遗产更受欢迎吗?有没有其他语言可以做得不同。
// CS0060.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
public class MyClass2 : MyClass // CS0060
{
public static void Main()
{
}
}
感谢
我很好奇为什么要开发这个规则。有人知道为什么这种遗产更受欢迎吗?有什么不同的语言吗?
第二个问题比第一个问题容易回答得多。是的,其他语言的做法不同。特别是,C++允许"私有继承";也就是说,继承关系成为类的私有实现细节。如果C#具有私有继承,那么显然基类的可访问性可能低于派生类。但是C#没有私有继承。
第一个问题很难回答,因为"为什么"问题本质上不适合堆栈溢出。"为什么要制定这条规则?"唯一正确的答案是"因为语言设计委员会认为,在给出许多相互竞争的设计目标时,这是最好的折衷方案"。
这可能不是一个令人满意的答案。要正确回答这个问题,不仅需要列出所有这些设计目标及其相对优点,还需要描述设计团队每个成员在做出决定时的心理状态,以及描述出现的各种冲突是通过什么过程解决的。这个决定是十三年前做出的,所以这条线索确实很冷。
13年前的那一天,我不在那个房间里,但我可以告诉你一些设计委员会在决定是否允许私人继承时会考虑的因素:
- 对"概念计数"的影响。(为了正确使用该功能,用户必须理解多少相关概念?该功能为语言添加了多少新概念?)
- 特性与C++的相似性或不相似性,这可能有帮助,也可能令人困惑
- C++中功能的成功。人们在C++中使用它吗?他们使用正确吗?是否每个C++用户都足够了解这个功能,从而做出正确的选择
- 与其他语言功能的交互量。这样的功能会以潜在的微妙或令人困惑的方式改变名称查找和重载解析
- 与相关语言特征的一致性水平。(允许不太容易访问接口。)
- 执行困难
- 还有更多的因素
由于我没有三四个小时的时间来写一份关于该功能所有因素的详细分析,然后尝试对设计团队进行追溯性分析,我认为你将不得不忍受你的好奇心得不到满足。
我建议以后不要在StackOverflow上问这样的问题。试着坚持关于实际代码的特定技术问题,这些问题有精确的答案
class BaseClass {...}
public class MyClass: BaseClass {...} // Error
http://msdn.microsoft.com/en-us/library/cx03xt0t.aspx
C#语言规范中提到了这一点,这也是非常合理的,因为在您的情况下,公共类可以在"公共"上下文中使用,公共可访问级别允许访问作为基类的非公共类,这将是错误的行为。
根据C#语言规范5.0:
(从下载规范http://www.microsoft.com/en-us/download/details.aspx?id=7029)
存在以下可访问性限制:
•类类型的直接基类必须至少与类类型本身一样可访问。
•接口类型的显式基本接口必须至少与接口类型本身一样可访问。
•委托类型的返回类型和参数类型必须至少与委托类型本身一样可访问。
•常数的类型必须至少与常数本身一样可访问。
•字段的类型必须至少与字段本身一样可访问。
•方法的返回类型和参数类型必须至少与方法本身一样可访问。
•财产的类型必须至少与财产本身一样可访问。
•事件的类型必须至少与事件本身一样可访问。
•索引器的类型和参数类型必须至少与索引器本身一样可访问。
•运算符的返回类型和参数类型必须至少与运算符本身一样可访问。
•实例构造函数的参数类型必须至少与实例构造函数本身一样可访问。
所有后续类必须至少与示例中的MyClass2具有相同的可访问性。
这是合乎逻辑的,因此下面的例子。
当您有一个内部类a,该类具有名为Prop。如果基类也不是公共的,你认为外界怎么会知道你派生的公共类B有一个属性Prop?
我明白你的意思,@mohammed sameeh。这有什么价值?或者,如果.net的行为有所不同,如果它试图允许这样做,会有什么副作用?
@Anirudh谈到了这个基础阶级的安全性。
如果你没有这个限制,持续隐藏"私人"/"内部"东西的安全模式可能会被打破,否则会非常混乱
这确实是最大的潜在副作用,错误地暴露了属性和方法。
由于根据定义,子类继承了父类的属性&方法,在这种情况下应该如何考虑
与其有(甚至更多)关于属性如何&方法在继承和子类化中是公开的,.net通过维护公开的层次结构并强制执行它来简化事情
其他人可能会对没有限制的类型转换或类似情况有一个很酷的看法。
当然,其他规则也可能存在。看到另一种不同的语言可能会很有趣。
但我们确实想要某种规则,所以当其他人使用你的类或程序集时,你知道会发生什么。
class MyClass
{
}
public class MyClass2 : MyClass // CS0060
{
public static void Main()
{
}
}
这个错误的原因是因为MyClass不是公共的,所以你需要把它放在公共的,只需在class MyClass
之前添加public