派生类可访问性

本文关键字:访问 派生 | 更新日期: 2023-09-27 17:57:03

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

例如,这将给出错误:不一致的可访问性:基类"基类"比类"派生类"更难访问

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

以及为什么在 Java 中允许它。

派生类可访问性

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

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

除了其他好的答案之外,请考虑此方案。您和您的同事 Alice 正在处理同一程序集的不同部分。爱丽丝写了一个类:

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

然后你写

public class EvenMoreComplicatedClass : ComplicatedClass
{
}

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

所以爱丽丝将她的代码更改为

internal class ComplicatedClass
{
    public void DoDangerousThing() { ... }
}
计算方法上没有必要将"

public"更改为"internal",因为 public 当然意味着"对可以看到这个类的东西公开",现在没有外部代码可以看到这个类。

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

为什么在Java中允许它?

不知道,对不起。

这样,使用标记为内部或私有的类就像它是公共的一样,只需执行空覆盖即可,就像您在示例中所做的那样。这将破坏将类标记为公共以外的任何目的。

internal

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

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

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

通常,我会在内部创建一个类,这样我就不必担心将来对它的公共接口进行版本控制。 我可以随时自由更改它,只要组装编译就可以了。 如果有人出现并公开曝光它,我现在将不得不永远保留该公共界面。