4

私は「レガシー コードを効果的に使用する」という本を読んでおり、単体テストでテストが難しいメソッドを偽の作成によってオーバーライドするという概念をいじっています。うまくいくと思った例をまとめたところ、予想とは異なる動作になりました。C# で継承とメソッドのオーバーロードがどのように機能するかについての理解に穴を発見したと思います。

私は次のインターフェースを持っています:

public interface IAnimal
{
    void MakeSound();
    void Move();
}

次に、動物インターフェイスの実装を次のように作成します。

public class Dog : IAnimal
{

public void MakeSound()
{
    Console.WriteLine("Woof");
}

public void Move()
{
    Console.WriteLine("Moved");
}

}

このクラスを次のように使用すると:

IAnimal myanimal = new Dog();
myanimal.MakeSound();
myanimal.Move();

次の出力が得られます。

ここで、Dog クラスの単体テストを行う必要があるとしますが、メソッドの 1 つである MakeSound() をオーバーライドする必要があります。これは、クラスのテストが何らかの理由で困難になっているためです。

Dog クラスを拡張し、MakeSound のメソッドを作成して、偽の犬を作成します。

public class FakeDog : Dog
{
    public void MakeSound()
    {
         Console.WriteLine("Bark");
    }
}

このクラスを次のように使用すると:

IAnimal myanimal = new FakeDog();
myanimal.MakeSound();
myanimal.Move();

次の出力が得られます。

私はそれが次のようになると予想していました: Bark Moved

ただし、FakeDog クラスにアニマル インターフェイスを実装して使用させると、次のようになります。

public class FakeDog : Dog, IAnimal
{
    public void MakeSound()
    {
         Console.WriteLine("Bark");
    }
}

次の出力が得られます: Bark Moved

Dog クラスを拡張したばかりのときに期待していたように、これがメソッドをオーバーライドする理由を理解したいだけです。誰かがこれについて私をまっすぐに設定できますか?

4

3 に答える 3

4

最初のケースでは、 の元の実装を隠す新しいメソッドを作成していますIAnimal.MakeSoundnewキーワードを使用してこれを明示的にすることを示唆する警告が表示されているはずです。

2 番目のケースでは、 を再実装し IAnimalています。インターフェースの実装にはキーワードは必要ありません(ただし、言語設計者overrideそれを要求していればよかったかもしれません)。

インターフェイスの再実装を避けるために、 でMakeSoundvirtual を作成しDog、 で明示的にオーバーライドすることができますFakeDog。その時点で考えられる解決策は 1 つだけであり、すべてがより簡単に理解できます。可能な限り、再実装とメソッドの隠蔽を避けるようにしています。

于 2010-02-11T10:42:21.803 に答える
2

(質問で答えて申し訳ありませんが、この実験は本当に参考になるかもしれません) 以下のように dog を実装するとどうなりますか:

public class Dog : IAnimal
{

public virtual void MakeSound()
{
    Console.WriteLine("Woof");
}

//...

「仮想」に注意してください

于 2010-02-11T10:39:34.780 に答える
1

MakeSoundクラスのようにメソッドを宣言virtualし、Dogクラスでオーバーライドする必要がありますFakeDog

public class Dog : IAnimal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Woof");
    }

    public virtual void Move()
    {
        Console.WriteLine("Moved");
    }
}

public class FakeDog : Dog
{
    public override void MakeSound()
    {
        Console.WriteLine("Bark");
    }
}
于 2010-02-11T10:42:06.273 に答える