派生类可访问性
本文关键字:访问 派生 | 更新日期: 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 字段。 如果更改值,这可能会导致错误。
通常,我会在内部创建一个类,这样我就不必担心将来对它的公共接口进行版本控制。 我可以随时自由更改它,只要组装编译就可以了。 如果有人出现并公开曝光它,我现在将不得不永远保留该公共界面。