为什么这有时意味着基地
本文关键字:意味着 为什么 | 更新日期: 2023-09-27 18:35:43
给定
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()
. 从狗身上取下Speak()
,突然this.Speak()
电话Animal.Speak()
. this
为什么会有这样的行为? 换句话说,为什么this
意味着base
或this
?
对我来说,明确呼吁base.Speak()
更有意义。 特别是当说话不是虚拟的时,令人惊讶的是,当virtual
被删除时,Speak()仍然被调用。 我从 OO 意义上理解 IS-A 关系,但我无法在 C# 中解决这个特定问题。 当人们编写上帝类UI时,这尤其烦人(几乎每个企业都这样做)。 当我应该查看"base"时,我正在"this"中寻找"Speak()"。
子分支自动从其基类继承行为。 如果您除了从Animal
继承Dog
之外不执行任何其他操作,则this.Speak()
和base.Speak()
都引用在 Animal
中实现的Speak()
版本。
特殊事情开始发生的地方是Dog
覆盖Speak()
。 除非virtual
Speak()
,否则这是不可能的。 (virtual
关键字不控制继承,它控制覆盖。
只有当Dog
覆盖Speak()
时,base.Speak()
才会做一些特别的事情:在这种情况下,调用Speak()
(或this.Speak()
)将执行Dog
的实现,因为它override
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"
不是那样。如果dog
内有一个说话方法,那么它就是基本方法的override
。如果不存在,则调用dogInstance.Speak将在Dog的任何基类中查找Speak()方法。
这是 OO 的基本点之一。如果未提供重写,则使用父方法。
此外,即使您删除了virtual
,也会调用Dog.Speak
,因为您没有以多态方式访问this
。
this
的意思是this
,没有别的。
在您的第一个示例中,您有一个覆盖Speak(..)
函数,因此this
调用该函数。
第二种情况下,istead,没有任何覆盖,所以它"爬"在派生树上并选择第一个合适的函数。在您的情况下,一个人是Animal
的Speak(..)
.
VB.Net 具有MyClass
关键字来执行此操作(与My
关键字相反,该关键字相当于C#中的this
)。 遗憾的是,C# 中没有MyClass
等效的关键字。