为什么只有在实现接口之后才会发生重写方法?
我一直在阅读《有效处理遗留代码》一书,并且一直在尝试通过创建假值来覆盖单元测试中难以测试的方法的概念。我整理了一个我认为可行的例子,但它的表现与我的预期不同。我想我刚刚发现了对 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 类时所期待的那样。谁能告诉我这一点吗?
I've been reading through the book Working Effectively with Legacy Code and I've been playing around with the concept of overriding difficult to test methods in unit tests via the creation of a fake. I put together an example of what I thought would work and it ended up behaving differently than I had been expecting. I think I've just discovered a hole in my understanding of how inheritance and method overloading works in C# and I was wondering if someone could help me understand what's going on here.
I've got the following interface:
public interface IAnimal
{
void MakeSound();
void Move();
}
I then create an implementation of the animal interface as follows:
public class Dog : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Woof");
}
public void Move()
{
Console.WriteLine("Moved");
}
}
When I use this class as follows:
IAnimal myanimal = new Dog();
myanimal.MakeSound();
myanimal.Move();
I get the following output:
Woof
Moved
Now, lets pretend that I'm needing to unit test the Dog class but one of the methods, MakeSound(), needs to be overridden because it is making the class difficult to test for some reason.
I create a fake dog by extending the Dog class and creating a method for MakeSound
public class FakeDog : Dog
{
public void MakeSound()
{
Console.WriteLine("Bark");
}
}
When I use this class as follows:
IAnimal myanimal = new FakeDog();
myanimal.MakeSound();
myanimal.Move();
I get the following output:
Woof
Moved
I had been expecting it to have been:
Bark
Moved
However, if I then have the FakeDog class implement the animal interface and use it:
public class FakeDog : Dog, IAnimal
{
public void MakeSound()
{
Console.WriteLine("Bark");
}
}
I get the following output:
Bark
Moved
I'm just wanting to understand the reason why this now overrides the method as I had been expecting when I had just been extended the Dog class. Can anyone set me straight on this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在第一种情况下,您要创建一个新方法,隐藏
IAnimal.MakeSound
的原始实现。您应该已经看到一条警告,建议您使用new
关键字来明确这一点。在第二种情况下,您重新实现
IAnimal
。实现接口不需要override
关键字(尽管如果语言设计者需要这样的要求可能会更好)。为了避免重新实现该接口,您可以在
Dog
中将MakeSound
设为虚拟,然后在FakeDog
中显式覆盖它。到那时,只涉及一种可能的解决方案,并且一切都更容易理解。我尽可能避免重新实现和方法隐藏。In the first case you're creating a new method which hides the original implementation of
IAnimal.MakeSound
. You should have seen a warning suggesting that you use thenew
keyword to make this explicit.In the second case you're re-implementing
IAnimal
. Implementing an interface doesn't require theoverride
keyword (although it might have been nice if the language designers had required that).To avoid re-implementing the interface, you could make
MakeSound
virtual inDog
, and then explicitly override it inFakeDog
. At that point there's only one possible resolution involved, and everything is simpler to understand. I try to avoid reimplementation and method hiding whenever possible.(很抱歉回答问题,但您可能真的会发现这个实验内容丰富)当您按如下方式实现狗时会发生什么:
注意“虚拟”
(Sorry for answering with a question, but you might genuinely find this experiment informative) What happens when you implement dog as follows:
Note the "virtual"
您需要在
Dog
类中将MakeSound
方法声明为virtual
,并在FakeDog 中覆盖它类:
You need to declare the
MakeSound
method asvirtual
in theDog
class and override it in theFakeDog
class: