为什么调用此重写方法
本文关键字:方法 重写 调用 为什么 | 更新日期: 2023-09-27 18:33:02
public interface ITimeable {}
public class TimedDoor : ITimeable {}
public static class Timer
{
public static void Add(ITimeable obj)
{
Console.Write("Add with parameter - ITimeable");
}
public static void Add(TimedDoor obj)
{
Console.Write("Add with parameter - TimedDoor");
}
}
public class BaseClient<T> where T : ITimeable
{
public T TimedDoorObject;
public virtual void Init()
{
Timer.Add(TimedDoorObject);
}
}
public class Client : BaseClient<TimedDoor>
{
public Client()
{
TimedDoorObject = new TimedDoor();
}
public override void Init()
{
Timer.Add(TimedDoorObject);
}
}
在此Client.Init()
返回"Add with parameter - TimedDoor"
但是如果客户端没有覆盖 Init(),
public class Client : BaseClient<TimedDoor>
{
public Client()
{
TimedDoor = new TimedDoor();
}
}
在这里,Client.Init()
返回"Add with parameter - ITimeable"
这是怎么回事? 在运行时,这两种情况下TimedDoorObject
相同。
如果我们添加一些显式强制转换,表示T
在调用Timer.Add(TimedDoorObject)
点表示的内容,则会使正在发生的事情更加明显。
public class BaseClient<T> where T : ITimeable
{
public T TimedDoorObject;
public virtual void Init()
{
Timer.Add((ITimeable)TimedDoorObject);
}
}
public class Client : BaseClient<TimedDoor>
{
public Client()
{
TimedDoorObject = new TimedDoor();
}
public override void Init()
{
Timer.Add((TimedDoor)TimedDoorObject);
}
}
因此,当BaseClient
被遵守时,它所知道的只是T
是某种ITimeable
对象,因此它能够链接到的最佳重载是void Add(ITimeable obj)
版本。相比之下,在编译时,Client
知道T
表示TimedDoor
,因此它使用 void Add(TimedDoor obj)
函数,因为它比 void Add(ITimeable obj)
匹配更好。
在运行时,TimedDoorObject 在这两种情况下都是相同的。
True,但该方法是根据调用参数时键入的内容来选择的,而不是它当前指向的对象的类型。因此,例如,即使td
是TimedDoor
,也会调用 ITimeable
方法:
TimeDoor td = new TimedDoor();
Timer.Add((ITimeable)td);
在基类的上下文中,TimedDoorObject
字段的类型为 ITimeable
。重写的Init
引用派生类的 TimedDoorObject
字段,该字段类型为 TimedDoor
。