c# - 为什么我们不能在 C# 中重写方法时更改访问修饰符?

标签 c# oop access-modifiers

在 C# 中,我们不能在重写基类的方法时更改访问修饰符。 例如

Class Base
{
   **protected** string foo()
   {
       return "Base";
   }
}

Class Derived : Base
{
   **public** override string foo()
   {
       return "Derived";
   }
}

这在 C# 中是无效的,它会给出编译时错误。

我想知道为什么不允许这样做。是否存在任何技术问题或是否会导致访问限制方面不一致???

最佳答案

更改派生类型中方法的访问修饰符毫无意义,这就是不允许这样做的原因:

案例 1:使用更严格的访问权限覆盖

由于以下情况,这种情况显然是不允许的:

class Base
{
    public virtual void A() {}
}

class Derived: Base
{
    protected override void A()
}

现在我们可以说:

List<Base> list;
list.Add(new Derived());
list[0].A() //Runtime access exception

案例 2:使用限制较少的访问修饰符覆盖

重点是什么?隐藏方法,你就完成了。 显然,如果有人通过基类型调用,他们将无法访问派生类型中定义的新方法,但这与基类型的作者想要的东西是一致的,所以你没有“权利”改变它。如果您想要从派生类调用派生类的细节,在这种情况下,new 方法工作得很好。

编辑:扩展案例 2

我在案例 2 中想说的是,如果您想更改可访问性,您已经有办法更改任何方法(虚拟或非虚拟)的可访问性。

考虑以下代码:

public class Base
{
    protected virtual string WhoAmI()
    {
        return "Base";
    }
}

public class Derived : Base
{
    public new virtual string WhoAmI()
    {
        return "Derived";
    }
}

public class AnotherDerived : Derived
{
    public override string WhoAmI()
    {
        return "AnotherDerived";
    }
}

使用 new 关键字,您已经有效地为您的 Derived 类创建了一个具有相同名称和签名的新虚拟方法。请注意,允许声明一个方法virtual,因此任何派生自Derived的类都可以覆盖它。

不允许有人做以下事情:

 Base newBaseObject = new Derived();
 newBaseObject.WhoAmI() //WhoAmI is not accessible.

但这个事实与是否能够覆盖 WhoAmI() 无关。无论如何,这种情况永远不会发生,因为 Base 没有声明一个 public WhoAmI()

因此在理论 C# 中,Derived.WhoAmI() 可以覆盖 Base.WhoAmI() 这样做没有实际好处,因为您永远无法无论如何从基类调用虚拟方法,所以 new 选项已经满足您的要求。

我希望这能让它更清楚。

关于c# - 为什么我们不能在 C# 中重写方法时更改访问修饰符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26757302/

相关文章:

php - 使用php获取父文件夹路径

perl - 是否存在与接口(interface)等效的 OO Perl?

inheritance - "public read-only"访问修饰符?

go - 公共(public),私有(private) - 大写,小写 :

java - 在这种情况下是否需要实现标准构造函数(Java)?

c# - 使用 Validator 属性(或替代属性)来验证结构

以 HashSet<int> 作为值的 c# 字典得到所有的交集

oop - Solidity 中的对象组合

c# - 我应该为 ObjectContext 使用 using 关键字吗?

c# - 将 T[] 转换为 IList<T> 有什么注意事项吗?