抽象和接口在一起

时间:2017-09-28 21:57:30

标签: vb.net

我正在努力理解抽象和界面方法。因为我明白了使用一个在另一个上的目的是什么是明确的。我试图在运行中找到使用它们两者的任何示例,但是所有教程都是如何使用接口而不是抽象,反之亦然,显示用于一个或另一个的用法。我真的很想看到一些实用的例子,它可以在一些现实生活中最好地展示两者。附加评论为什么在特定情况下你使用了另一个赞赏。在这样的例子中,非常欢迎泛型。

我将提出以下示例。我们有一些引擎可以从不同的位置获取文件,这些文件可以使用不同的协议进行,如下所示。我想在这个例子中理解如何通过接口和抽象来实现这一点。

'As all of protocol has to close and open would it be good to put in abstract?
abstract class Collector

    Protected Id
    Protected Name

    MustInherit Sub OpenConnection
    MustInherit Sub CloseConection

    End Class


    '?
    class Ftp : Collector

    class Sftp: Collector

    class Soap: Collector


    'Interface?
    Public Interface IRepository(Of T, Tkey)
    Function GetAllFiles() As IEnumerable(Of T)
    Function GetAllById(Tkey) as IEnumerable(Of T)
    End Interface

2 个答案:

答案 0 :(得分:2)

一些重要的区别:

  • 抽象类可以包含一些实现。界面不能。
  • 在.NET中,类不能从多个基类继承。
  • 可以实现多个接口

选择哪种方法取决于您。通常,它是组合模式或继承之间的选择。

组合使用接口。将对象视为拥有 X。

继承使用Classes。将对象视为 X。

在任何一种情况下,抽象类或接口都只是一个Type,您将通过它访问和操作它们。例如,如果您有一些代码要执行Insert / Update / Delete操作,则无需知道它在上运行的对象是< / em> FTP客户端 - 只有对象 能够支持这些操作。 (这正是IRepository指定的那样)

你绝对可以将两者结合起来。没有理由具体的FtpClient类不能从抽象Protocol类继承并且还实现IRepository接口。它甚至可以使用泛型!

接口非常适合解耦代码,也适用于单元测试模拟。

还有一个很好的总结和优点;关于Wikipedia (Composition_over_inheritance)的利弊。优点:

  

支持组合优于继承是一种设计原则,赋予设计更高的灵活性。从各种组件构建业务域类比尝试查找它们之间的共性和创建族树更自然。例如,油门踏板和车轮共享很少的共同特征,但它们都是汽车的重要组成部分。他们可以做什么以及如何利用它们来使汽车受益很容易定义。从长远来看,组合还提供了更稳定的业务领域,因为它不太容易出现家庭成员的怪癖。换句话说,最好是组合一个对象可以做什么(HAS-A)而不是扩展它是什么(IS-A)。

     

通过在单独的接口中识别系统对象行为而不是创建层次关系来通过继承在业务域类之间分发行为来简化初始设计。这种方法更容易适应未来的需求变更,否则需要在继承模型中完全重构业务域类。此外,它避免了通常与包含几代类的基于继承的模型的相对较小的更改相关的问题。

缺点:

  

使用组合而不是继承的一个常见缺点是,各个组件提供的方法可能必须在派生类型中实现,即使它们只是转发方法。相反,继承不要求在派生类中重新实现所有基类的方法。相反,派生类只需要实现(覆盖)具有与基类方法不同的行为的方法。如果基类包含许多提供默认行为的方法,并且只需要在派生类中重写其中一些方法,这可能需要大大减少编程工作量。

答案 1 :(得分:1)

我不明白为什么你想要一个结合两者的例子。我们只想说两者都是构建可靠软件架构的有效方法。它们只是两个工具 - 比如有一把菜刀和一把切肉刀。您不一定会一起使用它们,但在查看您想要的晚餐时,请看专业人士和骗子。

因此,如果您想提供一个共同点,通常会使用abstract / MustInherit类。子类派生自抽象类,必须像实现接口一样实现方法。这里的好处是抽象类可以提供可以集中开发的“基本逻辑”,所有子类都可以利用它。在最好的情况下,抽象类提供了一些“钩子”来插入子类中的特殊逻辑。

接口描述了类必须满足的要求。因此,接口定义的所有内容都必须在实现接口的类中实现。在这种方法中没有内置的可重用逻辑,如抽象基类,但接口的大“专业”是它们不会带走你可以从抽象类中得到的单一基类型。所以你可以从任何东西或任何东西派生,并仍然实现一个接口。 AND:您可以实现多个接口。

带有接口的“可重用逻辑”一词。虽然这并没有真正起作用,但.NET框架允许在类型(和接口)上编写extension methods来附加外部开发的代码。这允许使用诸如在其中实现的方法的接口重用代码。例如,您可以为接口None()编写扩展方法IEnumerable,该方法检查枚举是否为空。

public static bool None(this IEnumerable values)
{
    return !values.Any();
}

有了这个,None()可用于您的代码库中有权访问扩展方法的任何IEnumerable(实际上,Any()Select(),{{1 }等等也是扩展方法,位于Where()命名空间中。