Pourquoi ne remplaçant une méthode se produit seulement après que j'implémentent une interface?
-
19-09-2019 - |
Question
J'ai lu dans le livre Travailler efficacement avec Legacy Code et j'ai joué avec le concept de passer outre difficile de méthodes d'essai dans les tests unitaires par la création d'un faux. Je mets ensemble un exemple de ce que je pensais travailler et il a fini par se comporter différemment que je ne m'y attendais. Je pense que je viens de découvrir un trou dans ma compréhension de la façon dont fonctionne la surcharge héritage et méthode en C # et je me demandais si quelqu'un pouvait me aider à comprendre ce qui se passe ici.
J'ai l'interface suivante:
public interface IAnimal
{
void MakeSound();
void Move();
}
Je crée alors une implémentation de l'interface animal comme suit:
public class Dog : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Woof");
}
public void Move()
{
Console.WriteLine("Moved");
}
}
Quand j'utilise cette classe comme suit:
IAnimal myanimal = new Dog();
myanimal.MakeSound();
myanimal.Move();
Je reçois la sortie suivante: Trame Déplacé
Maintenant, fais semblant que je LETs ai besoin de test unitaire de la classe Dog, mais l'une des méthodes, MakeSound (), doit être ignoré car il rend la classe difficile à tester pour une raison quelconque.
Je crée un chien faux en étendant la classe de chien et de créer une méthode pour MakeSound
public class FakeDog : Dog
{
public void MakeSound()
{
Console.WriteLine("Bark");
}
}
Quand j'utilise cette classe comme suit:
IAnimal myanimal = new FakeDog();
myanimal.MakeSound();
myanimal.Move();
Je reçois la sortie suivante: Trame Déplacé
Je me attendais à été: Écorce Déplacé
Cependant, si je puis la classe FakeDog implémenter l'interface animal et de l'utiliser:
public class FakeDog : Dog, IAnimal
{
public void MakeSound()
{
Console.WriteLine("Bark");
}
}
Je reçois la sortie suivante: Écorce Déplacé
Je suis juste vouloir comprendre la raison pour laquelle cela l'emporte maintenant la méthode que je m'y attendais quand je venais d'être étendu la classe Dog. Quelqu'un peut-il me détromper à ce sujet?
La solution
Dans le premier cas, vous créez une nouvelle méthode cache la mise en œuvre originale de IAnimal.MakeSound
. Vous auriez dû voir un avertissement vous indiquant que vous utilisez le mot-clé new
pour en faire explicitement.
Dans le second cas, vous êtes réimplémenter IAnimal
. La mise en œuvre d'une interface ne nécessite pas le mot-clé override
(bien qu'il aurait été bien si les concepteurs de langue HAD que nécessaire).
Pour éviter une nouvelle implémentation de l'interface, vous pouvez faire MakeSound
virtuelle dans Dog
, puis explicitement dans remplacer FakeDog
. À ce moment-là, il n'y a qu'une seule résolution possible en jeu, et tout est plus simple à comprendre. J'essaie d'éviter reimplementation et cacher la méthode autant que possible.
Autres conseils
(Désolé pour répondre à une question, mais vous pourriez vraiment trouver cette expérience informative) Qu'advient-il lorsque vous implémentez chien comme suit:
public class Dog : IAnimal
{
public virtual void MakeSound()
{
Console.WriteLine("Woof");
}
//...
Notez le "virtuel"
Vous devez déclarer la méthode MakeSound
comme virtual
dans la classe Dog
et override dans la classe 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");
}
}