如果我们可以简单地覆盖超类的方法或使用抽象类,为啥还要使用接口? [复制]

Posted

技术标签:

【中文标题】如果我们可以简单地覆盖超类的方法或使用抽象类,为啥还要使用接口? [复制]【英文标题】:Why should we use interface if we can simply override methods of the superclass or use abstract classes? [duplicate]如果我们可以简单地覆盖超类的方法或使用抽象类,为什么还要使用接口? [复制] 【发布时间】:2015-03-02 21:06:17 【问题描述】:

我有两个程序,一个使用接口实现,另一个仅使用类实现 - 我读过使用接口的优点是它可以提供它自己的超类方法的实现,但可以使用抽象类或方法覆盖来完成。接口的用途是什么? 在什么样的层次结构和情况下使用接口最有利? 界面

interface Shape

    void area(int x, int y);

class Rectangle implements Shape

    @Override
    public void area(int length, int breadth)
    
        System.out.println(length*breadth);
    

class Triangle implements Shape

    @Override
    public void area(int base, int height)
    
        System.out.println(base*height);
    

public class ShapeUsingInterface

    public static void main(String X[])
    
        Rectangle r = new Rectangle();
        Triangle t  = new Triangle();

        r.area(5, 4);
        t.area(6, 3);
    

class Shape

    void Area(int x, int y)
    
        System.out.println(x*y);
    

class Rectangle extends Shape



class Triangle extends Shape

    @Override
    void Area(int base, int height)
    
        System.out.println((0.5)*base*height);
    

public class CalculateArea 

    public static void main(String X[])
    
        Rectangle r = new Rectangle();
        Triangle t = new Triangle();

        r.Area(4, 5);
        t.Area(6, 8);
    

【问题讨论】:

你可以实现多个接口,但只能扩展一个类 嗯,重要的区别在于,接口定义了一个牢不可破的合约。因此,它使实现它的类显式实现该方法。另一方面,一个类并不明确期望您实现这些方法。 【参考方案1】:

要解释为什么要使用接口,首先要了解继承的一个问题。它被称为Diamond Problem。简单来说,如果一个类D继承自两个类BC,而BC都继承自同一个类A,那么A中的方法的实现就是@ 987654330@得到?

我们留下的是Java 不喜欢的方法歧义!所以防止这种情况的方法是确保D 只能拥有一个超类,因此它可以继承自ABC,但不能超过一。这样可以避免问题,但我们失去了多重继承提供的所有好处!

进入界面。这允许我们拥有多重继承的好处(将单个类引用为各种不同的类型)并且仍然避免菱形问题,因为实现类提供了方法。这消除了方法的歧义。

这意味着,例如:

public abstract class MyClass 
    public void doSomething();


public class MyConcreteClass extends MyClass 
    public void doSomething() 
        // do something
    

您可以将MyConcreteClass 的实例引用为

 MyClass class = new MyConcreteClass();

 MyConcreteClass class = new MyConcreteClass();

但是,鉴于此实现,别无其他。您不能extend 更多课程,因为您可能会遇到钻石问题,但您可以包含Interface

public class MyConcreteClass extends MyClass implements Serializable 

突然间,你可以说..

Seralizable myClass = new MyConcreteClass();

因为myClass 是一个 Serializable。当一个方法可能不需要知道它是MyConcreteClass 的一个实例时,这对于将类彼此解耦非常有用,只需知道它具有必要的方法子集。

简而言之:你可以实现很多接口,但你只能继承一个类

【讨论】:

好答案。我还想在您的回答中看到您可以实现多个接口,但只能在此答案的某处将一个类扩展为一行。我希望阅读这篇文章,但没有直接看到。 @Joop 已为您添加。【参考方案2】:

接口定义契约。比如说:

interface MusicPlayer

  public void shuffle();

现在每个类实现接口可以有自己的算法来实现shuffle 方法,这取决于他们。抽象类类似于接口,其中抽象类定义几个方法是通用,而让其他方法以我们自己的方式实现。喜欢

abstract class MusicPlayer

  public void turnOff()
  
     //kill the app
  

  abstract public void shuffle();

使用接口,您可以实现多个接口,但只能扩展一个类。

【讨论】:

【参考方案3】:

我会说,在您的示例中,Shape 绝对不应该是类,而是接口。您已将面积计算的默认实现提供为x*y,但在大多数形状的情况下,此实现不正确。

如果您要添加新形状,您将继承执行不正确的方法。您必须记住检查所有类中的所有方法以验证继承的方法。在接口的情况下你不能犯这个错误。

【讨论】:

【参考方案4】:

您可以将interfaces 视为一种社会契约,它规定所有实现接口的类都应定义接口中声明的方法。这在实现它们的所有类之间创建了连续性,如果您希望所有这些类具有相同的行为,那就太棒了。由于接口不声明实现本身,因此将其留给实现它的类。通过这种方式,您可以创建许多具有启动按钮的机器,您可能希望它们都拥有。更好的说法是要求他们都拥有,社会契约确保了这种情况,因为你必须实现接口的每一个方法!这是编译器要求的。

class 覆盖了其他类的所有方法(通过扩展类并在其上实现)并不能真正表示它会始终真正信守承诺。知道班级将忠诚的好处已经消失,并且您掩盖了其背后的逻辑。查看是否所有方法都被覆盖将不太清楚,这是不好的做法。为什么不把你的逻辑说清楚,用一个接口实际实现社会契约。

抽象类有点不同,因为它们也实现了与普通类一样的方法,并且还作为接口工作,因为它们还要求您实现已声明但未实现的方法。在 java 8 接口中也可以做到这一点。

【讨论】:

由于默认实现,对于 java8,此答案不再完全正确。在 Java 8 中,接口也可能包含某些方法实现。

以上是关于如果我们可以简单地覆盖超类的方法或使用抽象类,为啥还要使用接口? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

模板方法

第6章:继承和抽象类

查看一个抽象类的方法是否未被其中一个扩展类覆盖的方法

设计模式

抽象abstract

接口和抽象类的区别。