Java中接口的重要性

假设我们有两个class, TigerAeroplane 。 这两种types的共同之处在于速度。 我知道创build一个超类ClassWithSpeed ,然后从它派生子类AeroplaneTiger是不合逻辑的。 相反,最好创build一个包含方法speed()的接口,然后在AeroplaneTiger实现它。 我明白了。 但是,我们可以做同样的事情,没有接口。 我们可以在Aeroplane定义方法speed() ,在Tiger定义方法speed() 。 唯一的(也许是非常大的)缺陷就是我们无法通过接口引用来“达到” TigerAeroplane的对象。

我是Java和OOP的初学者,如果有人向我解释接口的作用,我将不胜感激。 干杯!

它的:

 public int howFast(Airplane airplane) { return airplane.speed(); } public int howFast(Tiger tiger) { return tiger.speed(); } public int howFast(Rocket rocket) { return rocket.speed(); } public int howFast(ThingThatHasntBeenInventedYet thingx) { // wait... what? HOW IS THIS POSSIBLE?! return thingx.speed(); } ... 

VS

 public int howFast(Mover mover) { return mover.speed(); } 

现在,想象不得不回过头去改变将来的所有function。

接口或否,每个类将不得不实现或inheritancespeed()方法。 一个接口让你可以更容易地使用这些不同的类,因为它们都承诺以某种方式行事。 你将调用speed() ,他们将返回一个int ,所以你不必为每个可能的类编写单独的方法。

当你发现由于相对论物理学的突破,你需要不同的处理速度,你只需要更新调用speed()的方法。 当你的曾孙女写一个HyperIntelligentMonkeyFish类时,她不需要反汇编你的古代二进制文件,并进行修改,以便你的代码可以监视和控制她的突变军队。 她只需要声明HyperIntelligentMonkeyFish implements Mover

接口允许Java,因为它是静态types的,所以解决了多重inheritance限制,语言devise者认为这是值得的。

在dynamic语言(如Python,Ruby等)中,您可以对任意对象调用速度方法,并在运行时发现它是否存在。

另一方面,Java是静态types的,这意味着编译器必须同意该方法将在那里提前。 在不共享共同祖先并且可能只有Object的共同类的唯一方法是一个接口。

因为对象可以实现任意数量的接口,所以这意味着您可以毫无缺陷(两个超类中的冲突实现)获得多inheritance的好处(一个对象可以构成多个不同方法的不同对象)。

对于Java 8,这个语言的devise者得出结论:没有任何实现的接口过于严格(他们不喜欢我的解决scheme,我猜;-)),所以它们允许默认实现,从而扩展接口的多inheritance选项同时仍然试图通过一套复杂的优先规则来避免冲突的实现问题,以便执行一个明确的默认实现。

我试图用下面的例子来解释接口的优点 –

假设你有另一个class,你需要使用老虎或飞机作为参数。 所以通过使用界面你可以打电话使用

 someObject.someMethod(ClassWithSpeed) 

但如果你不使用接口,你可以使用

 someObject.someMethod(Tiger) someObject.someMethod(AeroPlane) 

现在你应该怎么做? 你可能的答案就像"I will use two overloaded method".

这是好的,但是

假设你需要添加更多的选项(比如说汽车,自行车,兔子,乌龟……等等)。 那么你会做什么来改变你现有的代码? 你将需要改变很多东西

上面的整个例子只有一个目的。 也就是说

“我们需要界面来创build一个更好,可重用和适当的面向对象的devise”

NB

  1. 如果你确定程序太小,你永远不需要改变它们,那么我认为没有接口就可以实现

通过定义接口,您可以定义不仅适用于Airplane和Tiger的方法,还适用于共享相同接口的其他类。

例如,说你的界面是IObjectWithSpeed。 然后你可以像这样定义一个方法 – 在IObjectWithSpeed对象上运行的一个类中。

  public double calculateSecondsToTravel( IObjectWithSpeed obj, double distance ) { return distance / obj.getSpeed(); } 

接口允许我们满足开放/closures的原则 – 开放延伸,但closures修改。 上述方法的单一实现不需要修改,因为定义了实现IObjectWithSpeed的新类。

我想进入很多的理论细节,但会试图解释使用这个例子。

考虑JDBC API 。 它是用来处理Java中数据库相关选项的API。 现在,这个行业有这么多的数据库。 如何为此写驱动程序? 那么,快速和肮脏的方法可能是使用我们自己的类和API编写自己的实现。

但从程序员的angular度来看。 他们会在使用不同的数据库时开始学习DATABASE DRIVER的API吗? 答案是不。

那么问题的解决scheme是什么? 只要有一个定义良好的API,任何人都可以为自己的实现扩展。

在JDBC API中,有一些接口是Connection,ResultSet,PreparedStatement,Statement等等。现在每个数据库供应商都会实现这个接口,并且会为他自己写一个实现。 结果? :减less开发人员的工作量,易于理解。

现在,这个自定义实现可能由什么组成? 这很简单。 他们做什么,以ResultSet接口为例,并以ResultSet的gettting返回的任何方法实现它,返回这样实现ResultSet接口的类

ResultSet rs = new ResultSetImpl(); //这是他们在内部做的事情

所以界面就像合同一样。 他们定义你的class级能够做什么,他们给你的应用程序的灵活性。 您可以使用适当的接口来创build自己的API。

希望这可以帮助你。

一个接口不仅仅是一个方法签名。

这是一种代表合同的types。 契约是事物,而不是方法签名。 当一个类实现一个接口时,这是因为有一个共享行为的契约,类有兴趣实现为一个types。 该合同是通过通常是方法体的指定成员实现的,但也可能包含静态最终字段。

老虎和飞机都可以被expression成一种具有通过速度实现的共同行为的types,如果这样的话,界面就代表了expression这种行为的合同。

除了描述这些类的function之外,还可以使用接口的方法,而不需要任何有关实现它的类的知识,即使对于尚未定义的类也是如此。

例如,如果您需要一个计算有效路线的类Transport ,则可以给它一个实现ClassWithSpeed作为参数的类,并使用其方法speed()来计算所需的值。 这样你就可以和我们的Aeroplane一起使用它,而且还可以和我们以后定义的任何类一起使用,比如Boat 。 Java会小心如果你想使用一个类作为Transport的参数,它将实现ClassWithSpeed ,并且任何实现ClassWithSpeedClassWithSpeed实现方法speed()以便它可以被使用。

编译器使用接口(作为一种语言结构)来certificate方法调用是有效的,并允许您使相关类与实现类交互,同时尽可能less地了解实现类。

给出一个简单的答案,这是一个非常广泛的问题。 我可以推荐一本书面向界面的devise:与模式 。 它解释了接口的所有function。 为什么我们不应该避免它们。

你有尝试过使用组合而不是吗?如果我想要2个不同的类inheritance相同的function我使用一个类,它采用抽象类和检查实例types的对象。 接口对于强制方法被包括在类中是有用的,但是不需要任何实现或者两个编码器小组在不同的编码区域上工作。

 Class Tiger { public MovingEntity mover; public Tiger(){ mover.speed=30; mover.directionX=-1; mover.move(mover); } } Class Plane { public MovingEntity mover; public Plane(){ mover.speed=500; mover.directionX=-1; mover.move(mover); } Abstract Class Moverable(){ private int xPos; private int yPos; private int directionX; private int directionY; private int speed; Class MovingEntity extends Moverable { public void move(Moverable m){ if(m instanceof Tiger){ xPos+=directionX*speed; yPos+=directionY*speed; }else if(m instanceof Plane){ xPos+=directionX*speed; yPos+=directionY*speed; } } 

在语言层面上,像你所说的那样,唯一使用接口的方法就是能够以一种通用的方式引用不同的类。 然而,在人员层面上,情况看起来有些不同:在大型项目中,IMO Java非常强大,这些项目的devise和实现都是由单独的人员完成的,而这些人员往往来自不同的公司。 现在,与其在Word文档中编写规范,系统架构师可以创build一堆类,然后实现者可以直接将其插入到IDE中并开始处理它们。 换句话说,它更方便,而不是声明“X类实现方法Y和Z,以便它被用于目的A,只是说”X类实现接口A“

因为创build界面给你多态性 ,横跨所有这些类,即老虎和飞机。

当基类的function将成为子类function的核心时,您可以从(抽象或具体)类扩展。

除了核心function之外,您还希望在您的类中添加增强function时使用接口。 所以使用接口会给你多态性,即使它不是你的类的核心function(因为你已经通过实现接口input了一个契约)。 与创build每个类的speed()方法相比,这是一个巨大的优势。