为什么这有时意味着基地

本文关键字:意味着 为什么 | 更新日期: 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意味着basethis

对我来说,明确呼吁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,没有任何覆盖,所以它"爬"在派生树上并选择第一个合适的函数。在您的情况下,一个人是AnimalSpeak(..).

VB.Net 具有MyClass关键字来执行此操作(与My关键字相反,该关键字相当于C#中的this)。 遗憾的是,C# 中没有MyClass等效的关键字。