在 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
类创建了一个具有相同名称和签名的新虚拟方法。请注意,允许声明 new
方法 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/6236909/