接口和合同:在这个例子中
接口和合同:在这个例子中
我试图理解“接口”,但几乎只看到了解释如何使用接口的文章,我的问题是理解“为什么”:
所以使用接口比创建和继承一个类更好,后者可能是多余的。
所以我们在类中实现接口方法,但我不明白这为什么是一件好事,
假设:
像Car.java
这样的类定义了制造汽车的所有代码
我们创建了接口Working.java
,其中包含一些方法,如start(),stop()等
我们在Diesel_Car.java
,Electric_Car.java
等类中实现这些方法
那么对于Car.java
来说有什么变化?这可能不是最好的例子,因为似乎Car应该是Diesel_Car.java
等的父类,
但在这些类中实现方法的意义是什么?
在Car.java
中是否有一种方法可以“调用”Diesel_Car.java
类及其接口方法?
我读到接口就像一个“合同”,但我只看到了这个合同的第二部分(方法的实现),我很难想象第一部分发生在哪里?
谢谢你的帮助。
在这个例子中,问题的出现是因为需要使用Collections.sort()方法对一个元素列表进行排序。该方法的签名是:<T extends java.lang.Comparable<? super T>> void sort(java.util.List<T> ts)
,这意味着sort()方法接受一个类型为T的对象列表,其中T是实现了Comparable接口的对象。
因此,如果想要使用Collections.sort()方法对一个对象列表进行排序,就需要让这些对象实现Comparable接口。比如,如果想要使用Collections.sort()方法对一个Car对象列表按照它们的重量进行排序,就需要在Car类中实现Comparable接口/合同。
在Comparable接口中,有一个compareTo()方法用于比较两个对象的大小。在Car类中,实现compareTo()方法如下:
public class Car implements Comparable<Car> { private int weight; //..其他类的实现内容 public int compareTo(Car otherCar) { if (this.weight == otherCar.weight) return 0; else if (this.weight > otherCar.weight) return 1; else return -1; } }
在排序时,Collections.sort()方法会调用compareTo()方法来进行比较。因此,实现了Comparable接口的Car类可以通过Collections.sort()方法进行排序。
通过这个例子,我们可以看到接口的作用是定义了一种约定(或合同),让其他类实现这个接口从而具备某种特定的行为。在这个例子中,实现了Comparable接口的类可以被Collections.sort()方法调用来进行排序。
解决这个问题的方法是让需要排序的类实现Comparable接口,并在实现的compareTo()方法中定义比较的逻辑。这样就可以使用Collections.sort()方法对该类的对象进行排序了。
这个例子也说明了接口的回调机制,即接口中定义的方法作为回调函数,由其他已经编写好的代码来处理。通过实现接口并提供相应的回调方法,可以在需要时被调用。
在这个例子中,问题是我们想要对添加到列表中的项目进行一些不寻常的操作,但我们无法更改第三方API。为了解决这个问题,我们创建了一个新的列表类型FrobbableList,它继承自ArrayList,并覆盖了add方法,在添加元素时执行自定义的操作。
通过使用List接口而不是具体的ArrayList类型作为第三方API的参数,我们可以轻松地将FrobbableList传递给API方法。如果第三方API要求传入的是ArrayList类型,那么我们无法这样做。通过不将API与特定的实现绑定在一起,它为我们提供了创建自定义行为的机会。
这个问题的解决方法是使用接口作为参数类型,而不是具体的实现类。这样可以使代码更具扩展性、可调试性和可测试性。这也是依赖注入和控制反转等概念的基础,它们依赖于面向接口的编程实现。
总之,通过使用接口而不是具体的实现类作为参数类型,我们可以更灵活地扩展和定制代码的行为,从而实现可扩展、可调试和可测试的代码。
在这个例子中,问题的出现是因为需要实现不同的接口以满足不同的功能需求。在这个例子中,汽车类(Car)有两个子类:电动车(Electric_Car)和柴油车(Diesel_Car)。汽车类可以实现以下接口:
1. Working接口:具有start()和stop()方法。
2. Moving接口:具有move()、turn()和stop()方法。
汽车类中可能包含一个AirConditioner类的实例,这个实例也应该实现Working接口。Driver对象可以与实现Working接口的对象进行交互,Driver可以启动(start())或停止(stop())汽车和空调(A/C)(司机可以分别启动或停止汽车和空调)。此外,由于司机可以独自行走(并不总是需要汽车),他应该实现Moving接口。Ground对象现在可以与任何实现Moving接口的对象进行交互:汽车或司机。
解决方法是使用接口来定义不同的功能需求,并让类实现这些接口。这样做的好处是,当对类进行修改时,只需要修改实现接口的类,而不需要修改整个类的层次结构和使用该类的其他类。
例如,假设我们有一个Driver类,有或没有驾照,Driver类将在一个类(比如World)中实现(仅作为示例)。通过创建Driver接口,并实现DriverWithLicence或DriverWithoutLicence类,我们可以在不修改代码、层次结构和使用Driver类的其他类的情况下,方便地更新代码。两个类都会实现各自的特点,Driver类在World类中的使用方式与以前完全相同,我们只是修改了driver1的行为,而不是整个Driver对象和它在World类中的使用方式,这样可以更容易地更新代码。
因此,接口和契约的使用可以使代码更容易更新和维护。