派生类可访问性

时间:2011-05-18 10:19:57

标签: c# java .net

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

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

internal class BaseClass
{
}

public class DerivedClass : BaseClass
{
}

为什么它在Java中被允许。

4 个答案:

答案 0 :(得分:11)

更新:此问题为the subject of my blog on November 13th 2012。谢谢你提出的好问题!

  

为什么在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中允许它?

不知道,抱歉。

答案 1 :(得分:9)

这样,使用标记为internal或private的类就像公共一样,只需执行空覆盖,就像在示例中一样。这样就无法将除了公开之外的任何东西标记为类别。

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

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

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