C# 编译器如何区分抽象方法的具体子类实现和抽象基类中的重载?
How does the C# compiler distinguish between a concrete subclass impl of an abstract method and an overload in the abstract base?
如果你有基础class
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));
}
}
和一个具体的class
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>();
确定上面显示的代码是否足以编译的规则是什么(如果可能的话,它们背后的原因)是什么:
- 在
concreteA
和 concreteB
上调用 KeyExists
有区别吗?
- 假设我们能以某种方式进入基础 class 方法
KeyExists(string key)
,我们能从中脱身吗?
对于问题 #2,我的意思是,如果编译器能够以某种方式编译此代码,它是否通过有效地向客户端隐藏基本方法来实现 - 因为如果到达该代码,它会导致在无限循环中?
在 convreteA
和 concreteB
上调用 KeyExists
最终是一样的。
Common Language Runtime (CLR)
知道调用实际类型的方法(使用 Virtual Method Table). This is the whole point of Polymorphism。它允许您将具体实现称为抽象实现,但实际调用的方法是具体类型.
在您给出的特定示例中,您不能从派生的 class 外部使用 KeyExists
的基础 class 实现,因为您无法创建实例摘要 class。如果它不是抽象的,您可以创建:
AbsHashtableish<string, Dinosaur> baseA = new AbsHashtableish<string, Dinosaur>();
并且 AbsHashtableish.KeyExists
会被调用。
编辑:(感谢 Oliver 的提醒)
您始终可以从派生 class 内部调用基础 class 实现。在这种情况下,您可以调用:
base.KeyExists(key)
如果你有基础class
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));
}
}
和一个具体的class
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>();
确定上面显示的代码是否足以编译的规则是什么(如果可能的话,它们背后的原因)是什么:
- 在
concreteA
和concreteB
上调用KeyExists
有区别吗? - 假设我们能以某种方式进入基础 class 方法
KeyExists(string key)
,我们能从中脱身吗?
对于问题 #2,我的意思是,如果编译器能够以某种方式编译此代码,它是否通过有效地向客户端隐藏基本方法来实现 - 因为如果到达该代码,它会导致在无限循环中?
在 convreteA
和 concreteB
上调用 KeyExists
最终是一样的。
Common Language Runtime (CLR)
知道调用实际类型的方法(使用 Virtual Method Table). This is the whole point of Polymorphism。它允许您将具体实现称为抽象实现,但实际调用的方法是具体类型.
在您给出的特定示例中,您不能从派生的 class 外部使用 KeyExists
的基础 class 实现,因为您无法创建实例摘要 class。如果它不是抽象的,您可以创建:
AbsHashtableish<string, Dinosaur> baseA = new AbsHashtableish<string, Dinosaur>();
并且 AbsHashtableish.KeyExists
会被调用。
编辑:(感谢 Oliver 的提醒)
您始终可以从派生 class 内部调用基础 class 实现。在这种情况下,您可以调用:
base.KeyExists(key)