为什么我们在Java中使用接口引用类型?

我即将参加我的第一个面向对象编程课程的期末考试,我仍然不了解多态性的概念。

假设我有一个抽象类“Vehicle”,这个类有一个名为“Aircraft”的子类。 我的问题是,这两个代码有什么不同?

Aircraft Jetplane = new Aircraft(); 

 Vehicle Jetplane = new Aircraft(); 

在第二个,然后Jetplane可能是从车辆inheritance的任何其他东西,而不仅仅是飞机。 例如,你可以有类似的东西

 Vehicle veh = null; if (someCondition) veh = new Aircraft(); else veh = new Boat(); 

这不能在第一个样本中完成,因为船不是飞机。

第一个不是多态的:喷气式飞机的编译时和运行时类型都是飞机。

第二个是多态的。 喷气式飞机的编译时类型是Vehicle,但运行时类型是Aircraft。

第二件事也发生了。 变量的类型确定哪些方法可见。 您可以声明接口类型或任何(包括抽象类)类型的变量。 您只能创建具体(非抽象)类类型的对象。

如果您的变量是接口类型,则接口中声明的所有方法都是可见的。 如果它是类类型,同样也是如此。

然而,该对象负责在该方法中进行实际工作。 通过这种方式,方法调用被“委托”给对象。

如果您的变量属于过于笼统的类型,则所需的方法将不可见。 如果它太具体,您将无法指出您可能需要的所有变量。 这是权衡。

正如Merlyn所说,解释多态性需要很长的篇幅,但让我试着用简单的例子来解释。

假设你被要求移动喷气式飞机和船,并检查它们是否都移动了。 然后你可以这样做:

 Aircraft jetPlane = new Aircraft(); jetPlane.moveForward(); boolean movementStatus = jetPlane.didItMoveForward(); Boat boat = new Boat(); boat.moveForward(); boolean movementStatus = boat.didItMoveForward(); 

或这个

 boolean moveIt(Aircraft plane) { plane.moveForward(); boolean movementStatus = jetPlane.didItMoveForward(); return movementStatus; } .... Aircraft jetPlane = new Aircraft(); boolean status = moveIt(jetPlane); .... boolean moveIt(Boat boat) { boat.moveForward(); boolean movementStatus = boat.didItMoveForward(); return movementStatus; } .... Boat boat = new Boat(); status = moveIt(boat); 

现在,正如您在上面所看到的,您必须为每种类型的车辆定义特定方法。 这将导致代码重复,并且代码不可重用。 这是多态性出现的地方。

假设您要以这种方式使用您的方法:

 boolean moveIt(Vehicle vehicle) { vehicle.moveForward(); boolean movementStatus = vehicle.didItMoveForward(); return movementStatus; } Aircraft jetPlane = new Aircraft(); boolean status = moveIt(jetPlane); Boat boat = new Boat(); status = moveIt(boat); 

如您所见,由于车辆实例(平面和船)的多态性,一种方法移动足以良好地重用逻辑。

HTH,K

根据ORACLE doc:

使用接口作为类型定义新接口时,您将定义新的参考数据类型。 您可以在任何可以使用任何其他数据类型名称的地方使用接口名称。 如果定义其类型为接口的引用变量,则分配给它的任何对象都必须是实现接口的类的实例。

作为一个例子,这里有一个方法,用于查找一对对象中的最大对象,对于从实现Relatable的类实例化的任何对象:

 public Object findLargest(Object object1, Object object2) { Relatable obj1 = (Relatable)object1; Relatable obj2 = (Relatable)object2; if ((obj1).isLargerThan(obj2) > 0) return object1; else return object2; } 

通过将object1转换为Relatable类型,它可以调用isLargerThan方法。

如果您在各种类中实现Relatable,则可以将从这些类中实例化的对象与findLargest()方法进行比较 – 前提是两个对象属于同一个类。 同样,它们都可以与以下方法进行比较:

 public Object findSmallest(Object object1, Object object2) { Relatable obj1 = (Relatable)object1; Relatable obj2 = (Relatable)object2; if ((obj1).isLargerThan(obj2) < 0) return object1; else return object2; } public boolean isEqual(Object object1, Object object2) { Relatable obj1 = (Relatable)object1; Relatable obj2 = (Relatable)object2; if ( (obj1).isLargerThan(obj2) == 0) return true; else return false; } 

这些方法适用于任何“可关联”对象,无论它们的类inheritance是什么。 当它们实现Relatable时,它们可以是它们自己的类(或超类)类型和Relatable类型。 这为他们提供了多重inheritance的一些优点,他们可以从超类和接口获得行为。

第二个利用多态性…虽然多态有时对arrays或列表更有利…但是想象你有多个inheritance自车辆的类可以说是平面,汽车和自行车,你有一个带有这些对象的数组CLASSE。 可能在您的程序中的某一点您可能希望所有车辆减速…如果之前您已宣布一系列车辆如:车辆arrays=新车辆[10]; 你可以简单地为数组中的Vehicle v做:v.slowDown()和类Car的方法slowDown,如果在数组中有一个对象car,将调用来自Plane的slowDown,如果它是一架飞机,等等……

第一例:

jetPlane是object of Aircraft Class舱的一个object of Aircraft Class 。 并且可以使用飞机类的所有属性和方法。

第二种情况:

jetPlane not an object 。 它是reference to object of Aircraft Class 。 尽管它是使用Aircraft类的构造函数创建的,但它only see and use the methods and attributes of the Vehicle Class and not the Aircraft class