3

与えられた

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このように振る舞うのですか?言い換えれば、なぜorthisを意味するのでしょうか? basethis

私にとっては、明示的な呼び出しのbase.Speak()方が理にかなっています。特に speak が virtual でない場合、驚くべきことに Speak()virtualは削除されても呼び出されます。オブジェクト指向の感覚から IS-A 関係を理解し​​ていますが、C# でこの特定の問題に頭を悩ませることはできません。これは、人々が神クラスの UI を作成する場合に特に厄介になります (実際にはすべての企業が行っています)。「base」を見なければならないときに、「this」内の「Speak()」を探しています。

4

5 に答える 5

3

というわけではありません。内にspeakメソッドある場合dog、それはoverride基本メソッドの1つです。そこにない場合は、dogInstance.Speakを呼び出すと、Dogの基本クラスのいずれかでSpeak()メソッドが検索されます。

于 2012-05-30T20:27:42.403 に答える
3

サブクラスは、基本クラスから自動的に動作を継承します。thenDogから継承する以外に何もせず、両方が で実装された のバージョンを参照している場合。Animalthis.Speak()base.Speak()Speak()Animal

特別なことが起こり始めるのは if DogoverridesSpeak()です。でない限り、これは不可能Speak()ですvirtual。(virtualキーワードは継承を制御するのではなく、オーバーライドを制御します。)

DogオーバーライドSpeak()が特別なことを行う場合のみ: その場合、 (または) をbase.Speak()呼び出すとの実装が実行されます。これはの実装であるためです。ここが役に立ちます。オーバーライドではなく基本クラスの実装を実行するように指定することで、この動作を回避できます。Speak()this.Speak()DogoverrideAnimalbase

このスタイルの一般的な用途は、コンストラクターです。例えば:

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"
于 2012-05-30T20:32:14.410 に答える
2

これは、OOの非常に基本的なポイントの1つです。オーバーライドを指定しない場合は、親メソッドが使用されます。

また、を削除しても、多態的にアクセスしていないためvirtual、が呼び出されます。Dog.Speakthis

于 2012-05-30T20:28:44.167 に答える
1

this意味し、他にはthis何もありません。

最初の例では、Speak(..)関数のオーバーライドがあるので、それthisを呼び出します。

2番目のケースでは、代わりにオーバーライドがないため、派生ツリーに「登り」、最初の適切な関数を選択します。あなたの場合、その1つはSpeak(..)ですAnimal

于 2012-05-30T20:28:40.703 に答える
0

VB.Netには、MyClassまさにそれを行うためのキーワードがあります(C#のMyキーワードと同等です)。this残念ながら、MyClassC#には同等のキーワードはありません。

于 2012-05-30T20:29:35.357 に答える