我刚刚在.net中遇到了关于继承的这个基本规则:
CS0060:类类型的直接基类必须至少与类类型本身一样可访问
我很好奇为什么要制定这条规则。
有谁知道为什么这种继承是首选? 是否有任何语言可以采用不同的方式。
// CS0060.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
public class MyClass2 : MyClass // CS0060
{
public static void Main()
{
}
}
由于
答案 0 :(得分:5)
我很好奇为什么要制定这条规则。有谁知道为什么这种遗传是首选的?是否有任何语言以不同的方式进行?
第二个问题比第一个问题更容易回答。是的,其他语言的表现不同。特别是,C ++允许“private inheritance”;也就是说,继承关系成为类的私有实现细节。如果C#具有私有继承,那么显然基类可能比派生类更难访问。但是C#没有私有继承。
第一个问题很难回答,因为“为什么”问题本质上不适合Stack Overflow 。唯一正确的答案是“为什么这条规则得到了发展?”是因为语言设计委员会在给出许多竞争性设计目标时决定这是最好的妥协“。
这可能不是一个令人满意的答案。正确回答这个问题不仅包括列出所有这些设计目标及其相对优点,还包括在决策时描述设计团队中每个成员的心理状态,还描述各种冲突的过程。出现了解决了。这个决定是在十三年前做出的,所以这条路确实很冷。
十三年前那天我不在那个房间,但我可以让你知道设计委员会在决定是否允许私人继承时会考虑的因素:
由于我没有三四个小时的时间,因此我需要对此功能的所有这些因素进行详细分析,然后尝试追溯性地对设计团队进行精神分析,我认为你是将无法满足你的好奇心。
我建议将来不要在StackOverflow上提出这样的问题。尝试坚持具有精确答案的实际代码的特定技术问题
答案 1 :(得分:3)
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下载规范)
存在以下辅助功能限制:
•类类型的直接基类必须至少与类类型本身一样可访问。
•接口类型的显式基接口必须至少与接口类型本身一样可访问。
•委托类型的返回类型和参数类型必须至少与委托类型本身一样可访问。
•常量的类型必须至少与常量本身一样可访问。
•字段的类型必须至少与字段本身一样可访问。
•方法的返回类型和参数类型必须至少与方法本身一样可访问。
•属性的类型必须至少与属性本身一样可访问。
•事件的类型必须至少与事件本身一样易于访问。
•索引器的类型和参数类型必须至少与索引器本身一样可访问。
•运算符的返回类型和参数类型必须至少与运算符本身一样可访问。
•实例构造函数的参数类型必须至少与实例构造函数本身一样可访问。
答案 2 :(得分:1)
所有后续类必须至少具有与示例中的MyClass2相同的可访问性。
这是合乎逻辑的,因此以下示例。
当你有一个名为Prop的公共财产的内部A类时。如果基类不公开,你认为外部世界会如何知道你的派生公共类B有属性Prop?
答案 3 :(得分:0)
我明白你的观点,@ emhammed sameeh。这有什么价值?或者,如果.net表现不同,如果它试图允许这样做会产生什么副作用?
当他谈到该基类的安全性时,@Anirudh正在谈论这个问题。如果你没有这个限制,那么一贯隐藏“私人”/“内部”事物的安全模式可能会被打破 - 或者非常令人困惑!
这确实是最大的潜在副作用,错误地暴露了属性和方法。
因为子类根据定义继承了父类的属性&方法,在这种情况下应该如何考虑? 而不是(甚至更多)关于属性和属性的规则。方法在继承和子类化中公开,.net通过维护公开的层次结构并强制执行它来简化事情。
其他人可能会有一个很酷的观点来说明在没有限制的情况下输入类型的内容会发生什么。
当然可能存在其他规则。看到另一种语言不同的做法可能会很有趣。
但是我们确实需要某种规则,所以当别人消耗你的课程或集会时,你知道会发生什么。
答案 4 :(得分:0)
class MyClass
{
}
public class MyClass2 : MyClass // CS0060
{
public static void Main()
{
}
}
此错误的原因是因为 MyClass 不是公开的,因此您需要将其设为公开,只需在 public
之前添加 class MyClass