【问题标题】:derived class accessibility派生类可访问性
【发布时间】:2011-08-27 22:32:05
【问题描述】:

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

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

internal class BaseClass
{
}

public class DerivedClass : BaseClass
{
}

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

【问题讨论】:

    标签: c# java .net


    【解决方案1】:

    更新:这个问题是the subject of my blog on November 13th 2012。谢谢你的好问题!

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

    除了其他好的答案之外,请考虑这种情况。您和您的同事 Alice 正在处理同一个程序集的不同部分。 Alice 写了一个类:

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

    然后你写

    public class EvenMoreComplicatedClass : ComplicatedClass
    {
    }
    

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

    所以 Alice 将她的代码更改为

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

    确定不需要在方法上将“public”更改为“internal”,因为 public 意味着“对可以看到此类的事物公开”,现在没有外部代码可以看到此类。

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

    为什么在 Java 中允许?

    不知道,抱歉。

    【讨论】:

    • 感谢您的详细解答。
    【解决方案2】:

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

    【讨论】:

    • 在这种情况下为什么允许拥有比类具有更大可访问性的方法
    • @NDeveloper - 所以你可以覆盖基类方法。
    【解决方案3】:

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

    【讨论】:

    • The user of DerivedClass may not have or have access to the DLL that BaseClass is in so DerivedClass can't depend on it. 你是不是建议你不能从不同 DLL 中的类继承?
    • 没有。我已将 可能 加粗以使其更清晰。
    【解决方案4】:

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

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

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

    【讨论】:

    • 虽然我同意你的观点,但这个例子的动机很差。如果一个常量发生了变化,那么它本来就不应该是一个常量。仅对实际恒定的事物使用常量:一打鸡蛋的数量、铅的原子序数、pi 的值等等。如果它可能改变,它就不是一个常数。
    • 是的,你是对的。我应该想出一个不那么做作的例子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    相关资源
    最近更新 更多