多态性不';不能在Java中使用方法参数
我编写了以下代码:多态性不';不能在Java中使用方法参数,java,oop,polymorphism,Java,Oop,Polymorphism,我编写了以下代码: class Plane {} class Airbus extends Plane {} public class Main { void fly(Plane p) { System.out.println("I'm in a plane"); } void fly(Airbus a) { System.out.println("I'm in the best Airbus!"); } publi
class Plane {}
class Airbus extends Plane {}
public class Main {
void fly(Plane p) {
System.out.println("I'm in a plane");
}
void fly(Airbus a) {
System.out.println("I'm in the best Airbus!");
}
public static void main(String[] args) {
Main m = new Main();
Plane plane = new Plane();
m.fly(plane);
Airbus airbus = new Airbus();
m.fly(airbus);
Plane planeAirbus = new Airbus();
m.fly(planeAirbus);
}
}
结果是:
I'm in a plane
I'm in the best Airbus!
I'm in a plane
不出所料,前两次调用给出了我在飞机上
和我在最好的空中客车上代码>分别为
Plane planeAirbus = new Airbus();
该方法将此对象视为平面,即使真实对象是一个平面。即使我将抽象
添加到类平面
,也没有任何变化,最后一次调用的结果仍然是我在一个平面
所以问题是为什么多态性在方法参数和调用中不起作用?这有什么目的吗?它是如何工作的 这里的问题是Java不支持方法参数的动态绑定。您看到的是静态绑定,即要调用的方法的重载是在编译时选择的
另请参见:以下输出的原因:
I'm in a plane
I'm in the best Airbus!
I'm in a plane
因为它正在执行重载,而重载是静态多态或编译时多态。在重载中,类可以有多个同名但参数类型不同的方法。在您的示例中,Plane
是Plane planeAirbus=new Airbus()的类型代码>方法重载类型多态性在Java中是在编译时确定的
这意味着Java必须从它们表示的引用类型推断出方法参数的类型,因为它不知道它们在编译时持有的对象的类型。
我们可以说,在这种情况下,Plane类型的引用保存Airbus类型实例是非常清楚的。然而,这并不是那么简单,因为空客实例本身可能是一个方法参数,它可以保存任何子类实例或空客实例本身
唯一安全的方法是不解析父链,并将引用作为其面值的实际引用变量类型。另一种方法是实现与重写相同的方法重载,并使用对象的运行时绑定进行解析。我不知道为什么不这样做,因为这样会使方法重载和重写更加统一
以下是来自
调用方法时(§15.12),在编译时使用实际参数(以及任何显式类型参数)的数量和参数的编译时类型来确定将调用的方法的签名(§15.12.2)。如果要调用的方法是实例方法,则将在运行时使用动态方法查找(§15.12.4)确定要调用的实际方法。
Java重载是编译时多态性。因此,当您将planeAirbus
声明为Plane
时,它将调用fly(Plane)
事实上,classMain
不应该知道飞机和空客可以飞行。
更好的it设计:
public interface Flyable{
void fly();
}
public Plane implements Flyable{
void fly(){
//do something
}
}
public Airbus implements Flyable{
void fly(){
//do something
}
}
然后在Main
类中
public static void main(String[] args) {
Flyable plane = new Plane();
plane.fly();
Flyable airbus = new Airbus();
airbus.fly();
}
动态绑定的另一个名称是双重分派还是有不同的概念?我认为双重分派是不同的,但是双重分派通常也实现动态绑定,所以它们经常一起出现。双重分派可以在Java中通过使用访问者模式来实现,因为Java是一种静态类型的语言。