【问题标题】:What to use here, abstract class or Interface? [duplicate]这里用什么,抽象类还是接口? [复制]
【发布时间】:2012-08-04 02:23:20
【问题描述】:

我有一个抽象类说 CTest,它只包含抽象方法 f1() 而没有别的。类似地,我有一个接口ITest,只有方法f1()。这里 CTest 抽象类和 ITest 接口都做同样的事情。

一个区别是,接口提供了灵活性,它可以在任何已经派生自其他类但抽象类不能的类中实现。

除了上面的区别,这两者之间的实际区别是什么?哪一个在这里有效(CTest 或 ITest)?我什么时候应该用什么? OO 设计中的任何特定场景以及对此的任何一般性建议都是有帮助的

【问题讨论】:

标签: c# java oop class interface


【解决方案1】:

除了继承,它取决于场景。用一个很好的例子检查this code project article

[来自文章]

假设你需要创建三个类,第一个是 CAR,第二个是 男人,第三个是女人。现在您需要在每个函数中定义一个函数 他们如何移动。现在所有三个都可以移动,但 CAR 完全移动 与男人和女人不同的方式。所以这里我们使用一个接口 IMOVEMENT 并在其中声明一个函数 MOVE。现在所有三个类都可以 继承这个接口。所以课程是这样的。

public interface IMovement
{
    void Move();
}

public class Car : IMovement
{
    public void Move()
    {
        //Provide Implementation
    }
}

public class Man : IMovement
{
    public void Move()
    {
        //Provide Implementation
    }
}

public class Woman : IMovement
{
    public void Move()
    {
        //Provide Implementation
    }
}

但是,由于 MAN 和 WOMAN 走路的方式相似,所以提供相同的 两种不同方法中的行为将是代码冗余,更简单 字码不重复使用。所以我们现在可以定义一个抽象类 人类运动,所以这个类可以是 HUMANBEINGMOVEMENT。还 同样可以应用于 CAR 类,因为有很多 汽车制造商和所有汽车都以类似的方式移动,所以我们也可以 为汽车运动定义一个抽象类,它可以是 CARSMOVEMENT。 所以我们重构的代码将是。

public interface IMovement
{
    void Move();
}

public abstract class CarsMovement : IMovement
{

    public virtual void Move()
    {
        //default behavior for cars movement
    }
}

public class SuzukiCar : CarsMovement
{
    public override void Move()
    {
        //Provide Implementation
    }
}

public abstract class HumanBeingMovement : IMovement
{

    public virtual void Move()
    {
        //default behavior for human being movement
    }
}

public class Man : HumanBeingMovement
{
    public override void Move()
    {
        //Provide Implementation
    }
}

public class Woman : HumanBeingMovement
{
    public override void Move()
    {
        //Provide Implementation
    }
}

【讨论】:

  • 如果有人想知道,这些冒号用于替换“implements”关键字。
  • @hamad:这个例子很好地解释了接口和抽象类的用法。但就我而言,这两者的实际差异是什么?我应该使用哪一个?
  • @mhn 如果您想为所有派生类实现一些通用功能,那么您应该使用 f1() 中的抽象类。如果您将 f1 设为虚拟,那么它也可以被子类覆盖。另一方面,接口描述了一组可以属于任何类或结构的相关功能。如果没有共同的功能,那么你应该使用接口,因为通常理解,如果有抽象类,那么就会有一些虚拟方法。
【解决方案2】:

Java 中更喜欢Interfaces 而不是Abstract Classes。请参阅 Effective Java

中的第 18 条

要点

  • 可以改进现有类以实现新接口。

  • 接口是定义 mixin 的理想选择。

  • 接口允许构建非分层类型框架。

  • 接口可实现安全、强大的功能增强。

【讨论】:

    【解决方案3】:
    【解决方案4】:

    对我来说最好在这里使用界面。当您可以在那里提取一些代码时(您可以实现方法或有其他想要调用它的东西),应该使用抽象类。

    【讨论】:

      【解决方案5】:

      在这种情况下没有区别,但 CTest 类具有唯一可以作为 Class 继承的类。但是 ITest 接口可以同时被其他类和接口继承。

      【讨论】:

        【解决方案6】:

        在你提到的场景中,只有一种方法,没有定义,最好的方法是接口。

        接口在 Java 中的主要优势在于您可以实现多个接口,但您只能扩展一个类。因此,如果您已经在扩展一个抽象类,那么您将无法选择扩展任何其他类。

        黄金法则:如果我们只需要,接口就比抽象类好 定义方法而不是声明它们。

        虽然说接口在你的情况下更好,但程序员也应该从未来的角度考虑他的代码。你觉得你正在创建的类/接口将来会有更多的方法吗?您想定义这些方法还是只声明?回答这些问题会让您知道接口是否足够或需要抽象类。

        【讨论】:

          【解决方案7】:

          优势:

          抽象类的实现优于接口,因为抽象类的方法查找比接口快。如果你修改你的接口,你必须更新你的实现类,但抽象类的任何修改,对实现类没有影响。

          缺点:

          If you want to implement more than one parent class method , it is not possible.
          But regarding to interface you can implement more than one.
          

          【讨论】:

            【解决方案8】:

            在这种情况下,假设您的抽象类将只包含抽象方法,在我看来,您应该使用接口。具有抽象方法和接口的抽象类具有相同的目的,但是,您可以仅扩展一个类,但可以实现任意数量的类,因此如果您决定从其他类继承某些功能,则可以使您的代码不易发生重大变化。

            关于您的问题:但这两者之间的实际区别是什么?哪一个在这里有效(CTest 或 ITest)?我什么时候应该用什么? OO 设计中的任何特定场景以及对此的任何一般性建议都是有帮助的

            接口类似于契约,当一个类实现一个接口时,它保证了一个实现。当有人想提供功能但不想透露内部代码时,这通常很有帮助,因此开发人员只会丢弃接口,这样您就可以在不知道每个方法是如何实现的情况下进行调用。显然,您可以实现任意数量的接口。

            抽象类允许您创建一个类,该类具有指定的某些行为和一些留待将来实现的行为。然而,与接口不同的是,每个类只能扩展一个类,因此从这个角度来看,您应该谨慎扩展类。抽象类还允许您将行为注入一个类并使其自动传播到其子类。这通常使开发/维护的某些部分更容易。

            【讨论】:

            • 另一方面,您可以在不破坏现有代码的情况下对抽象类进行更改。 MSFT 的 C# 最佳实践建议在设计系统时尽可能使用抽象类,以最大程度地减少未来对重大更改的需求。
            • @MichaelGraczyk:我同意,因此我在第一行的假设是:假设您的抽象类将只包含抽象方法。不过,我会将其添加到我的回复的最后一部分
            • @Michael/npinti:我知道我们可以在不破坏更改的情况下对抽象类进行更改,但在接口中是不可能的。但是如果你在现有的抽象类中添加一个抽象方法,它仍然会作为接口中断......它在这里有什么不同或灵活性吗?
            • @mhn 增加的灵活性来自于能够在不破坏框架用户的情况下扩展您的框架。您可以将新的虚拟成员添加到具有默认实现的抽象类,但不能将新成员添加到接口。例如,MSFT 在 .NET 4.0 中添加了System.IO.Stream.CopyTo 方法。如果是Stream 一个接口,他们不可能做到这一点。
            猜你喜欢
            • 2012-09-12
            • 2011-06-04
            • 2021-12-17
            • 2010-11-13
            • 2013-02-17
            • 2014-01-02
            • 2010-09-20
            相关资源
            最近更新 更多