我即将参加我的第一个面向对象编程课程的期末考试,但我仍然不了解多态性的概念。
假设我有一个抽象类“Vehicle”,这个类有一个名为“Aircraft”的子类。我的问题是,这两个代码有什么不同?
Aircraft Jetplane = new Aircraft();
和
Vehicle Jetplane = new Aircraft();
答案 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
。