困惑于JAVA接口

10

可能重复:
什么是“面向接口编程”?
接口与抽象类(通用OO)

我是新手学习JAVA,现在我对接口很困惑。我已经搜索和阅读了许多资料,但仍不清楚。

当我尝试查找一些关于接口的信息时,我看到许多人谈论接口和抽象类之间的关系。但我甚至不知道他们为什么要将这两者进行对比。因为我认为抽象类用于告诉其他人,您不能创建此抽象类的对象,如果想要,则必须修改该抽象类。这与继承有关,对吗?

但我不知道接口的意义所在。有一个interface a,如果class B要实现接口a,它必须使用保留字class B implements a,然后完成接口要求的所有方法。但我的问题是,如果class B必须自己完成所有方法,那接口的意义在哪里?我认为我们不需要它。我不太理解。我读了许多句子,例如:“接口可以反映面向对象语言的核心思想”,“接口可以帮助使程序更容易”等等。但我真的无法理解。

那么,有没有人可以向我展示一些例子来让我理解接口?或者您可以告诉我一些有用的链接或清晰描述接口的书籍。我真的希望搞清楚。谢谢!


这篇文章可能会帮助你更深入地了解Java中的接口:https://dev59.com/3XRC5IYBdhLWcg3wMd5S - Jimmy
接口的唯一目的是实现“公开定义的协议行为”,这意味着继承接口的类必须遵循该接口定义的所有方法,这是一个规则,更具体地说,它是该类的“协议定义”。(无论如何,在接口中定义的所有内容都必须是公共的)。 - Lion
5个回答

10

假设你有一个Car类和一个Vegetable类,实际上两个类之间没有关联,但是有一个通用的行为叫做wash(),因为我们可以洗车,也可以洗蔬菜。但是洗车和洗蔬菜是完全不同的过程/行为。

例如:Car应该使用高压泵来清洗,而Vegetables则应该在您的厨房水槽下清洗。所以你把这个洗涤过程定义为接口中的方法wash(),并实现它们在CarVegetable类中。

interface Washable {

 public void wash();

} 

public class Car implements Washable {

 public void wash() {

   // wash the car with a power pump

 }


}

public class Vegetable implements Washable {

public void wash() {

   // wash the vegetable under a kitchen sink

 }


}

作为一个人,你可能需要洗车也需要洗蔬菜。

public class Person  {


Washable washableObject = new Car();

washableObject.wash();

washableObject = new Vegetable();

washableObject.wash();




}
  1. 接口是一种连接具有共同行为但不相关的类的方式。但实现这种行为将会有不同的实现,或者在未来可能会改变。

  2. 有一天你决定改变洗车的方式。假设你购买了一个“洗车机”。因此,在Car类中的wash()方法内部进行了实现更改。

    public class Car implements Washable {

  public void wash() {

   // wash the car with my new car washing machine !!

 }

}

但作为一个人,你仍然调用 wash() 方法。 wash() 方法的实现方式已经改变(使用你新的洗车机来洗车),但这个实现变化并没有影响到你的 Person 类。

希望您现在清楚为什么我们现在使用接口了。


太好了!非常生动清晰!谢谢! - lkkeepmoving
1
非常清晰易懂。但是为什么呢?我看不到任何好处。你知道你正在洗一辆车,因为你将它实例化为一个新的Car()。你可以只有一个名为Washable的父类,使wash()成为抽象方法,并让Car和Vegetables都继承自Washable,实现它们各自版本的wash()。我错过了什么吗? - SMBiggs
2
@ScottBiggs 假设你有一个名为SuperWashMachine的类,其中有一个名为washAll()的方法。它接收一个Washable数组。你只需要遍历这个数组并调用wash()方法,因为“合同”规定任何实现Washable接口的类都知道如何洗涤。这就是全部,这个方法甚至不需要知道任何特定的汽车、蔬菜或其他类,它只处理可洗涤的物品。为什么不使用继承呢?嗯,也许这是语义上的问题。理想情况下,除了被洗涤以外,汽车和蔬菜应该有更多的共同点,才能建立一个具有共同父类的“is a”关系。 - Mauricio Martinez
我们也可以使用抽象类来处理相同的任务,那么为什么您没有在这里使用抽象类而是使用了接口? - nirazverma

1
一个简单的代码,用于理解接口和类。
import java.util.List;
import java.util.ArrayList;
public class Q01 {
List<Shape> shapes= new ArrayList();

public void add() {
    shapes.add(new Square(3.0));
    shapes.add(new Circle(2.0));
}
public void print() {
    for (int i = 0; i < shapes.size(); i++) {
        Shape shape = shapes.get(i);
        System.out.println(shape.getClass().getSimpleName() + " --->" + shape.getArea());
    }
}

public static void main(String[] args) {
    Q01 q01= new Q01();
    q01.add();
    q01.print();
}

public interface Shape {
    double getArea();
}

public class Square implements Shape{
    private double edge;

    public Square(double edge) {
        this.edge = edge;
    }
    public double getArea() {
        return edge*edge;
    }
}
public class Circle implements Shape{
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getArea() {
        return 3.14 * radius * radius;
    }
}
}

在Q01类中,“List<Shape> shapes= new ArrayList();”的类型必须是“List<Shape>”吗?为什么? - lkkeepmoving
因为我们不确定它的类型,它可能是圆形还是正方形? - chrome

1

基本上,接口是一种实现多重继承的方式,而不必真正去做。 (这并不是说Java开发人员“退缩了”——多重继承非常混乱和低效。)

这意味着您可以拥有两个完全独立的类A和B,除了Object之外没有共同的祖先,并且如果它们实现相同的接口,则可以将一个替换为另一个(只要引用接口中的方法即可)。


这里的答案虽然不完整,但是是最好的。 - SMBiggs

1

在接口方面,可以将其视为类和用户之间的契约。当一个类实现了一个接口时,它就承诺提供接口定义的所有方法。


@Ravn 糟糕的詞語 xD 抱歉。已經修正。 - David Moreno García
我们也可以通过抽象类获得相同的行为,那么为什么我们在这里不使用呢? - nirazverma

1

假设您了解类继承,我认为接口就像一个骨架类,描述了类的结构但实际上并没有编写/实现。

然后,另一个类可以与任何实现特定接口的类一起工作,即使尚未实现该接口。

例如,有人可能创建一个名为Animal的接口。它的方法可能是:Talk()Walk()Eat()。您可以编写一个实现AnimalDog类,当调用Talk()方法时打印“woof”。因此,另一个类将知道如何使用实现Animal接口的所有类。

更新

一个很好的现实世界的例子是JDBC数据库语句接口。这定义了数据库制造商必须实现的一些必需属性,例如execute(String sql)。Oracle将以不同于Postgresql的方式实现此功能。这允许将数据库替换为另一个,但用户代码保持不变。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接