如果您有基础班

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>();


确定上面显示的代码是否足以编译的规则是什么(如果可能,还需要其背后的推理)?


KeyExistsconcreteA上调用concreteB有什么区别?
假设我们可以以某种方式输入基类方法KeyExists(string key),我们是否可以摆脱它?


对于问题2,我的意思是,如果编译器能够以某种方式编译此代码,那么它是否通过对客户端有效地隐藏基本方法来完成-因为如果到达该代码,则会导致无限循环?

最佳答案

最终,同时在KeyExistsconvreteA上调用concreteB都是一样的。

Common Language Runtime (CLR)知道调用实际类型的方法(使用Virtual Method Table)。这是Polymorphism的重点。它允许您将具体的实现称为抽象的实现,但是实际调用的方法是具体的类型。

在您给出的特定示例中,您不能从派生类的外部使用KeyExists的基类实现,这仅仅是因为您无法创建抽象类的实例。如果不是抽象的,则可以创建:

AbsHashtableish<string, Dinosaur> baseA = new AbsHashtableish<string, Dinosaur>();


然后AbsHashtableish.KeyExists将被调用。

编辑:(感谢奥利弗的注意)

您始终可以从派生类内部调用基类实现。在这种情况下,您可以致电:

base.KeyExists(key)

10-08 14:21