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

时间:2011-07-10 18:45:46

标签: java polymorphism

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

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

Aircraft Jetplane = new Aircraft();

Vehicle Jetplane = new Aircraft();

7 个答案:

答案 0 :(得分:13)

在第二种情况下,Jetplane可能是继承自Vehicle的其他任何东西,而不仅仅是飞机。例如,您可能会有类似

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

在第一个样本中无法做到,因为船不是飞机。

答案 1 :(得分:5)

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

第二个是多态的。编译时类型的jetplane是Vehicle,但运行时类型是Aircraft。

答案 2 :(得分:3)

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

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

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

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

答案 3 :(得分:3)

正如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

答案 4 :(得分:1)

根据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;
}

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

答案 5 :(得分:0)

第二个利用多态性...虽然多态有时对数组或列表更有利...但想象你有多个继承自车辆的类可以说平面,汽车和自行车,你有一个数组与这些classe的对象。可能在您的程序中的某一点您可能希望所有车辆减速...如果之前您已宣布一系列车辆如: 车辆阵列=新车[10]; 你可以这样做 对于车辆v阵列:     v.slowDown() 如果在数组中有一个对象车,则会调用从类Car的方法slowDown,如果它是一个Plane,也会调用Plane的slowDown,等等......

答案 6 :(得分:0)

第一种情况:

jetPlane是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