给定
public class Animal
{
public Animal()
{
Console.WriteLine("Animal constructor called");
}
public virtual void Speak()
{
Console.WriteLine("animal speaks");
}
}
public class Dog: Animal
{
public Dog()
{
Console.WriteLine("Dog constructor called");
this.Speak();
}
public override void Speak()
{
Console.WriteLine("dog speaks");
base.Speak();
}
}
this.Speak()
调用 Dog.Speak()
。从 dog 中删除 Speak()
并突然 this.Speak()
调用 Animal.Speak()
。为什么 this
会这样?换句话说,为什么 this
表示 base
或 this
?
对我来说,显式调用 base.Speak()
更有意义。特别是当 speak 不是虚拟的时,令人惊讶的是,当 virtual
被移除时 Speak() 仍然被调用。我从 OO 的角度理解 IS-A 关系,但我无法解决 C# 中的这个特定问题。当人们编写上帝级 UI 时(实际上每个企业都这样做),这会变得特别烦人。当我应该查看“base”时,我正在“this”中寻找“Speak()”。
最佳答案
子类自动从它们的基类继承行为。如果除了从 Animal
继承 Dog
之外什么都不做,那么 this.Speak()
和 base.Speak()
都引用了 Animal
中实现的 Speak()
版本。
如果 Dog
覆盖了 Speak()
,就会开始发生特殊的事情。这是不可能的,除非 Speak()
是 virtual
。 (virtual
关键字不控制继承,它控制覆盖。)
只有当 Dog
覆盖 Speak()
时,base.Speak()
才会做一些特别的事情:在这种情况下,调用 Speak ()
(或this.Speak()
)将执行Dog
的实现,因为它覆盖
的Animal
的实现。这就是 base
变得有用的地方:它允许您通过指定要执行基类的实现而不是覆盖来绕过此行为。
此样式的常见用途是在构造函数中。例如:
public class Animal
{
private readonly string _name;
public Animal() : this("Animal") { }
protected Animal(string name) { _name = name; }
public void Speak() { Console.WriteLine(_name + " speaks"); }
}
public class NamedAnimal : Animal
{
public NamedAnimal(name) : base(name) { }
}
// usage:
(new Animal()).Speak(); // prints "Animal speaks"
(new NamedAnimal("Dog")).Speak(); // prints "Dog speaks"
在此示例中,NamedAnimal
无法访问 _name
字段,但它仍然可以通过调用基类的构造函数来间接设置它。但是基类的签名与基类中的签名相同,所以必须使用base
来指定。
对于非构造函数,获取无法以其他方式访问的行为也很有用。例如,如果 Animal.Speak
是虚拟的,那么我们可以使用覆盖将行为附加到它上面,而不是简单地替换它:
public class NamedAnimal : Animal
{
public NamedAnimal(name) : base(name) { }
public override Speak()
{
Console.Write("The animal named ");
base.Speak();
}
}
// usage:
(new NamedAnimal("Dog")).Speak(); // Writes "The animal named Dog speaks"
关于c# - 为什么这有时意味着基础?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10823720/