我一直在通读 Working Effectively with Legacy Code 这本书,并且一直在研究通过创建伪造来覆盖单元测试中难以测试的方法的概念。我整理了一个我认为可行的示例,结果它的行为与我预期的不同。我想我刚刚发现我对 C# 中的继承和方法重载如何工作的理解存在漏洞,我想知道是否有人可以帮助我理解这里发生的事情。
我有以下界面:
public interface IAnimal
{
void MakeSound();
void Move();
}
然后我按如下方式创建动物接口(interface)的实现:
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 类实现动物接口(interface)并使用它:
public class FakeDog : Dog, IAnimal
{
public void MakeSound()
{
Console.WriteLine("Bark");
}
}
我得到以下输出: 吠 移动
我只是想了解为什么这会像我刚刚扩展 Dog 类时所期望的那样覆盖该方法。任何人都可以直接告诉我这个吗?
最佳答案
在第一种情况下,您要创建一个新方法,该方法隐藏 IAnimal.MakeSound
的原始实现。您应该已经看到一条警告,建议您使用 new
关键字来明确这一点。
在第二种情况下,您正在重新实现 IAnimal
。实现接口(interface)不需要 override
关键字(尽管如果语言设计者需要那样做可能会更好)。
为避免重新实现接口(interface),您可以在 Dog
中将 MakeSound
设为虚拟,然后在 FakeDog
中显式覆盖它。到那时,只涉及一种可能的解决方案,而且一切都更容易理解。我尽量避免重新实现和隐藏方法。
关于c# - 为什么仅在实现接口(interface)后才重写方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2243830/