在派生类型中更改方法的访问修饰符是没有意义的,这就是不允许这样做的原因:
案例 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 选项已经满足您的要求。
我希望这会让它更清楚。