在c#中实现多态性,如何做到最好?

第一个问题在这里,所以希望你们都会轻轻地对我说话!

在过去的几天里,我一直在阅读关于多态的非常多的内容,并试图将它应用到我在c#中所做的事情,似乎有几种不同的方法来实现它。 我希望我已经掌握了这个,但即使我没有澄清,我也很高兴。

从我所看到的,我有3个选择:

  1. 我可以从基类inheritance并在我希望派生类重写的任何方法上使用关键字’ virtual ‘。
  2. 我可以用虚方法实现一个抽象类,并以这种方式实现,
  3. 我可以使用界面吗?

从我所看到的,如果我不需要基础中的任何实现逻辑,那么一个接口给了我最大的灵活性(因为我当然不限制我自己的多重inheritance等),但如果我需要基础为了能够在派生类正在做的事情之上做一些事情,那么使用1或2将是更好的解决方案?

感谢有关这些人的任何意见 – 本周末我已阅读了很多内容,无论是在本网站还是其他地方,我认为我现在理解这些方法,但我只是想以语言特定的方式澄清如果我在右边跟踪。 希望我也正确地标记了这一点。

干杯,特里

界面提供最多的抽象; 您不依赖于任何特定的实现(如果由于其他原因,实现必须具有不同的基类,则非常有用)。

对于真正的多态性, virtual是必须的; 多态性最常与类型子类化相关联……

你当然可以混合两者:

 public interface IFoo { void Bar(); } class Foo : IFoo { public virtual void Bar() {...} } class Foo2 : Foo { public override ... } 

abstract是一个单独的问题; abstract的选择确实是:它可以由基类理智地定义吗? 如果没有默认实现,则它必须是abstract

当存在许多常见的实现细节时,常见的基类可能很有用,并且纯粹通过接口复制是没有意义的; 但有趣的是 – 如果实现永远不会因每个实现而有所不同,那么扩展方法提供了一种在interface上公开它的有用方法(这样每个实现都不必这样做):

 public interface IFoo { void Bar(); } public static class FooExtensions { // just a silly example... public static bool TryBar(this IFoo foo) { try { foo.Bar(); return true; } catch { return false; } } } 

以上所有三个都是有效的,并且本身就是有用的。 没有“最好”的技术。 只有编程实践和经验才能帮助您在合适的时间选择合适的技术。

因此,选择一个现在似乎合适的方法,并实施。 观察哪些有效,哪些失败,吸取教训,然后再试一次。

接口通常受到青睐,原因如下:

  • Polymorphisme是关于契约,inheritance是关于重用
  • inheritance链很难正确(特别是单inheritance,请参阅Windows窗体控件中的设计错误,其中可滚动性,富文本等function在inheritance链中进行了硬编码
  • inheritance会导致维护问题

也就是说,如果你想利用常见的function,你可以使用接口进行多态(让你的方法接受接口),但使用抽象基类来共享一些行为。

 public interface IFoo { void Bar(); enter code here } 

将是你的界面

 public abstract class BaseFoo : IFoo { void Bar { // Default implementation } } 

将是您的默认实现

 public class SomeFoo : BaseFoo { } 

是一个重用您的实现的类。

不过,你将使用接口来实现多态:

 public class Bar { int DoSometingWithFoo(IFoo foo) { foo.Bar(); } } 

注意我们正在使用方法中的接口。

你应该问的第一件事是“为什么我需要使用多态?”,因为多态不是最终本身,而是达到目的的意思。 一旦您明确定义了问题,就应该更清楚地使用哪种方法。

无论如何,你评论的这三个方法并不是独占的,如果你需要在一些类之间重用逻辑而不是其他类,或者需要一些不同的接口,你仍然可以混合它们……

  • 使用抽象类来强制执行类结构
  • 使用接口来描述行为

这实际上取决于您希望如何构建代码以及您希望如何使用它。

从测试的角度来看,具有Interface类型的基类是很好的,因为您可以使用模拟对象来替换它。

如果您希望在某些函数中实现代码而不是其他函数,那么抽象类就是如此,就像抽象类只有抽象函数一样,它实际上是一个接口。

请记住,抽象类无法实例化,因此对于工作代码,您必须具有从中派生的类。

实际上所有都是有效的。

我倾向于使用抽象类,如果我有很多从它派生的类,但是在浅层(比如说只有1个类)。

如果我期待深层次的inheritance,那么我使用具有虚函数的类。

无论如何,最好保持简单的类,以及它们的inheritance性,因为它们越复杂,它们就越有可能引入错误。