派生类可访问性

为什么在C#中,派生类不允许具有比其基类更大的可访问性。

例如,这将给出错误:不一致的可访问性:基类’BaseClass’比类’DerivedClass’更难访问

internal class BaseClass { } public class DerivedClass : BaseClass { } 

为什么它在Java中被允许。

更新 :这个问题是我的博客2012年11月13日的主题 。 谢谢你这个好问题!

为什么在C#中,派生类不允许具有比其基类更大的可访问性?

除了其他好的答案,请考虑这种情况。 你和你的同事爱丽丝正在研究同一组件的不同部分。 爱丽丝写了一堂课:

 public class ComplicatedClass { public void DoDangerousThing() { ... } } 

然后你写

 public class EvenMoreComplicatedClass : ComplicatedClass { } 

大。 现在,Alice从Bob获得安全审查,他们意识到(1)没有客户需要使用ComplicatedClass,(2)DoDangerousThing暴露了恶意代码可以利用的安全漏洞。 内部代码当然没有。

所以Alice将她的代码更改为

 internal class ComplicatedClass { public void DoDangerousThing() { ... } } 

确定没有必要在方法上将“公共”更改为“内部”,因为当然公共意味着“公共事物可以看到这个类”,现在没有外部代码可以看到这个类。

当Alice使用此更改重新编译时,您的代码会发生什么? 它应该无法编译 。 您假设用户需要查看基类,并且Alice已做出违反该假设的更改。 安全的做法是让编译器告诉Alice她需要和你谈谈,这样你就可以解决这个问题,而不会让客户暴露在DoDangerousThing的漏洞之下。

为什么在Java中允许它?

不知道,对不起。

这样,使用标记为内部或私有的类就像公共一样,只需执行空覆盖,就像在示例中一样。 这会破坏除了公开之外的任何标记类的目的。

internal与Java中的package privateDerivedClass的用户可能没有或无法访问BaseClass所在的DLL,因此DerivedClass不能依赖它。 在Java中,包隐私是一个更宽松的概念 – 但在您的示例中, DerivedClass必须与BaseClass位于同一个包中,因此客户端用户很可能拥有这两个类,因此Java允许它。

因为否则您将比预期更多地暴露BaseClass成员。

一个问题的例子是public const int Age 。 这是可以的,因为它只在同一个程序集中公开,因此版本控制是安全的。 如果现在使用inheritence使类成为公共,那么您将在constcily之外公开此const字段。 如果值发生变化,这可能会导致错误。

我经常在内部制作一个类,这样我就不必担心将来版本化它的公共接口。 我随时可以随意更改它,只要那个程序集合就可以了。 如果有人出现并公开曝光,我现在必须永远重新审视公共界面。