c# - 为什么仅在实现接口(interface)后才重写方法?

标签 c# inheritance interface extending-classes

我一直在通读 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/

相关文章:

python - 如何在 Python 3.4+ 中写入抽象属性

ruby - 是否可以从父类创建子类的实例?

java - 如何定义抛出通用异常类型的接口(interface)?

javascript - AngularJS $资源参数名称

c#异常处理,实际例子。你会怎么做?

c# - Azure 服务总线中的队列生命周期是多少?

c# - 多线程问题——向静态列表中添加一个元素

c# - 使用自己的 xml 解析器和 system.xml 命名空间之间的性能差异有多大

javascript - 从子类调用父类(super class)函数的正确方法

interface - COM双接口(interface)