如果您有基础班
public abstract class AbsHashtableish<TKey, TValue>
{
public abstract TKey ConvertToKey(string key);
public abstract bool KeyExists(TKey key);
public virtual bool KeyExists(string key)
{
Console.WriteLine("In Base");
return KeyExists(ConvertToKey(key));
}
}
和一个小班
public class ConcreteHashtableish: AbsHashtableish<string, Dinosaur>
{
...
public override string ConvertToKey(string key)
{
return key;
}
public override bool KeyExists(string key)
{
Console.WriteLine("In Sub");
return _list.Contains(key);
}
}
和客户A
AbsHashtableish<string, Dinosaur> concreteA = new ConcreteHashtableish<string, Dinosaur>();
和客户B
ConcreteHashtableish<string, Dinosaur> concreteB = new ConcreteHashtableish<string, Dinosaur>();
确定上面显示的代码是否足以编译的规则是什么(如果可能,还需要其背后的推理)?
在
KeyExists
和concreteA
上调用concreteB
有什么区别?假设我们可以以某种方式输入基类方法
KeyExists(string key)
,我们是否可以摆脱它?对于问题2,我的意思是,如果编译器能够以某种方式编译此代码,那么它是否通过对客户端有效地隐藏基本方法来完成-因为如果到达该代码,则会导致无限循环?
最佳答案
最终,同时在KeyExists
和convreteA
上调用concreteB
都是一样的。Common Language Runtime (CLR)
知道调用实际类型的方法(使用Virtual Method Table)。这是Polymorphism的重点。它允许您将具体的实现称为抽象的实现,但是实际调用的方法是具体的类型。
在您给出的特定示例中,您不能从派生类的外部使用KeyExists
的基类实现,这仅仅是因为您无法创建抽象类的实例。如果不是抽象的,则可以创建:
AbsHashtableish<string, Dinosaur> baseA = new AbsHashtableish<string, Dinosaur>();
然后
AbsHashtableish.KeyExists
将被调用。编辑:(感谢奥利弗的注意)
您始终可以从派生类内部调用基类实现。在这种情况下,您可以致电:
base.KeyExists(key)