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

时间:2009-06-01 07:19:01

标签: c# oop polymorphism

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

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

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

  1. 我可以从基地继承 class并使用关键字 关于我的任何方法的'virtual' 想要我的派生类 覆盖。
  2. 我可以用虚方法实现一个抽象类 这样做,
  3. 我可以使用界面吗?
  4. 从我所看到的,如果我不需要基础中的任何实现逻辑,那么一个接口给了我最大的灵活性(因为我当时并没有限制自己关于多重继承等),但如果我要求基础能够在派生类正在做的事情之上做一些事情,那么使用1或2将是更好的解决方案吗?

    感谢您对这些人的任何意见 - 本周末我已经阅读了很多内容,无论是在本网站还是其他地方,我我现在理解这些方法,但我只想澄清一下如果我在正确的轨道上,语言特定的方式。希望我也正确标记了这一点。

    干杯, 特里

6 个答案:

答案 0 :(得分:6)

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

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

你当然可以混合两者:

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

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

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

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;
        }
    }
}

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

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

  • Polymorphisme是关于合同,继承是关于重用
  • 继承链很难正确(特别是对于单继承,请参阅Windows窗体控件中的设计错误,其中诸如可滚动性,富文本等功能在继承链中进行了硬编码
  • 继承导致维护问题

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

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();
}
}

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

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

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

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

在实践中,所有都是有效的。

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

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

无论如何,最好保持课程简单,以及他们的继承性,因为越复杂,他们就越有可能引入错误。