C# - 多态性混淆了重载和方法隐藏
本文关键字:重载 方法 隐藏 多态性 | 更新日期: 2023-09-27 18:00:51
我有一个名为Item
的类,它充当抽象类,但没有定义为抽象类。此类具有MaxPerStack
属性:
public class Item
{
public short MaxPerStack
{
get
{
return this.Data.MaxPerStack;
}
}
}
我还有一个名为 Equip
的类,它派生自 Item
类,并且还有一个名为 MaxPerStack
的属性,该属性声明为 new
:
public class Equip : Item
{
public new short MaxPerStack
{
get
{
return 1;
}
}
}
我有以下方法称为Add
,它使用item
的MaxPerStack
属性:
public void Add(Item item)
{
Console.WriteLine("Stack: {0}.", item.MaxPerStack);
}
当我这样做时:
Add(new Equip());
它归Item
的MaxPerStack
属性,而不是Equip
属性。
为什么会这样?
因为你没有将Item.MaxPerStack
标记为virtual
,也没有将Equip.MaxPerStack
标记为override
。 你需要做这两件事才能获得你期望的行为。
通过将基类型的方法隐式标记为sealed
并将派生类型显式标记为new
可以阻止虚拟调度,这是用于确保在基类型上调用的方法将执行与对象的实际运行时类型关联的实现的确切机制,而不是将方法静态绑定到对象的编译时类型中的实现。
这里的问题是您的Equip
类替换了在Item
类上定义的 MaxPerStack
属性。
public class Equip : Item
{
public new short MaxPerStack
{
get
{
return 1;
}
}
}
MSDN 告诉您:
如果派生类中的方法前面有 new 关键字,则该方法被定义为独立于基类中的方法。
..
使用 new 关键字告诉编译器您的定义隐藏了基类中包含的定义。这是默认行为。
这也适用于属性。这告诉您Equip
将具有自己的非相关MaxPerStack
版本。因此,当您调用Item.MaxPerStack
时,您正在访问Item
类上的属性,而不是Equip
类。不管你传入的Item
是否真的是一个Equip
类。
若要解决此问题,可以将 MaxPerStack
属性设置为虚拟,然后在 Equip
类中重写它。
public class Item
{
public virtual short MaxPerStack
{
get
{
return this.Data.MaxPerStack;
}
}
}
public class Equip : Item
{
public override short MaxPerStack
{
get
{
return 1;
}
}
}
现在,当您提供Equip
作为参数时 Add(Item)
,Add
方法将改为访问 Equip
类上的 MaxPerStack
属性。
MSDN 告诉您:
如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法而不是基类方法。