Почему переопределение метода происходит только после реализации интерфейса? - PullRequest
4 голосов
/ 11 февраля 2010

Я читал книгу «Эффективная работа с унаследованным кодом» и изучал концепцию переопределения сложных тестовых методов в модульных тестах путем создания фальшивки. Я собрал пример того, что, как я думал, сработает, и в итоге он вел себя не так, как я ожидал. Я думаю, что только что обнаружил дыру в моем понимании того, как наследование и перегрузка методов работают в 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, но один из методов, MakeSound (), необходимо переопределить, поскольку по какой-то причине затрудняет тестирование класса.

Я создаю поддельную собаку, расширяя класс Dog и создавая метод для MakeSound

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

Когда я использую этот класс следующим образом:

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

Я получаю следующий вывод: гав Переехал

Я ожидал, что это будет: Лай Переехал

Однако, если у меня есть класс FakeDog, реализующий интерфейс животных и использующий его:

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

Я получаю следующий вывод: Лай Переехал

Я просто хочу понять причину, по которой это переопределяет метод, как я и ожидал, когда меня только что расширили в классе Dog. Может кто-нибудь прямо на меня это поставить?

Ответы [ 3 ]

4 голосов
/ 11 февраля 2010

В первом случае вы создаете новый метод, который скрывает оригинальную реализацию IAnimal.MakeSound. Вы должны были увидеть предупреждение, предлагающее использовать ключевое слово new, чтобы сделать это явным.

Во втором случае вы повторно реализуете IAnimal. Для реализации интерфейса не требуется ключевое слово override (хотя было бы неплохо, если бы разработчики языка требовали ).

Чтобы избежать повторной реализации интерфейса, вы можете сделать MakeSound виртуальным в Dog, а затем явно переопределить его в FakeDog. На данный момент существует только одно возможное решение, и все проще для понимания. Я стараюсь по возможности избегать повторной реализации и сокрытия методов.

2 голосов
/ 11 февраля 2010

(извините за ответ на вопрос, но вы можете искренне найти этот эксперимент информативным) Что происходит, когда вы реализуете собаку следующим образом:

public class Dog : IAnimal
{

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

//...

Обратите внимание на "виртуальный"

1 голос
/ 11 февраля 2010

Вам необходимо объявить метод 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");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...