[英]Dynamic Binding and Overriding/Overloading in java
public abstract class Vector{
public abstract double norm();
}
public class PlanarVector extends Vector {
protected final double x;
protected final double y;
public PlanarVector(double x, double y){
this.x=x;
this.y=y;
}
public double norm(){
return Math.sqrt(x*x+y*y);
}
public PlanarVector sum(PlanarVector v){
return new PlanarVector(x+v.x, y+v.y);
}
public String toString(){
return "x=" + x + " y=" + y;
}
}
public class SpaceVector extends PlanarVector {
protected final double z;
public SpaceVector(double x, double y,double z){
super(x,y);
this.z=z;
}
public double norm(){
return Math.sqrt(x*x + y*y + z*z);
}
public SpaceVector sum(SpaceVector v){
return new SpaceVector(x+v.x, y+v.y, z+v.z);
}
public String toString(){
return super.toString() + " z=" + z;
}
}
public class TestVector {
public static void main ( String[] args ) {
Vector v0 ;
PlanarVector v1 , v2 ;
SpaceVector v3 , v4 ;
v1 = new PlanarVector ( 3 , 4 ) ;
v0 = v1 ;
v2 = new SpaceVector ( 2 , 3 , 6 ) ;
v3 = new SpaceVector ( 2 , 1 , 0 ) ;
v4 = v3 ;
System.out.println(v1.sum(v2)) ; //expected output: x=5 y=7 realoutput: x=5 y=7 (v1 can only use PlanarVectorMethods because its dynamic and static type is PlanarVector)
System.out.println(v2.sum(v1)) ; //expected output: x=5 y=7 realoutput: x=5 y=7
System.out.println(v2.sum(v3)) ; //expected output: 'x=4 y=4 z=6' realoutput: 'x=4 y=4'
System.out.println(v3.sum(v2)) ; //expected output: 'x=4 y=4 z=6' realoutput: 'x=4 y=4'
System.out.println(v3.sum(v4)) ;
System.out.println(v1.norm()) ;
System.out.println(v2.norm()) ; //expected output: sqrt(13) realoutput: 7
}
}
有人能解釋一下為什么“System.out.println(v2.sum(v3))”中的 v2.sum(v3) 不使用子類方法嗎? 我知道 v2 的 static 類型是 PlanarVector 但它的動態類型是 SpaceVector 同樣適用於 System.out.println(v3.sum(v2)), static 和 v3 的動態類型是 SpaceVector 而 v2 在這里被認為是 planarVector? 為什么?。 最后一個 System.out.println(v2.norm()) 這次將 v2 視為 SpaceVector..? 怎么了,? 我還有最后一個問題,超類不能使用子類方法,即使它是子類的實例,對吧? 如果該方法是子類中的重寫方法會發生什么,為什么超類現在可以使用它(並使用子類實現)?
我在問一個關於 java 基礎知識的問題,希望通過示例獲得簡單明了的答案。
方法SpaceVector sum (SpaceVector)
在 SpaceVector 中不是PlanarVector sum (PlanarVector)
的覆蓋
在 PlanarVector 中,但只是一個重載。
這兩種方法都存在於 SpaceVector 中。 它不是覆蓋,因為簽名不同(傳遞的參數不是同一類型)。
其次,Java 沒有實現多參數分派,而是通過使用簡單的虛擬表僅實現單參數分派。 明確地說,這意味着它只查看第一個參數來動態決定調用哪個方法,而在 Java 中,(非靜態)方法的第一個參數始終是隱式的 this 引用。 this 引用基本上決定了在哪個方法中查看虛擬表。 其他 arguments 總是在編譯時解析,從不動態解析。 一些語言實現了多參數分派,但不是 Java。
如果將這兩個信息放在一起,您就可以理解為什么實際調用的方法不是您預期的方法:您傳遞了一個聲明類型為 PlanarVector 的 object,因此調用的方法是PlanarVector sum(PlanarVector)
。 編譯器不知道,實際上無法知道您是否有對 PlanarVector 或子類的引用。
嘗試更改 v2 和 v3 的聲明,您將看到不同之處。 也可以嘗試使用 var 關鍵字並觀察會發生什么。 自己試驗一下就明白了,挺有意思的。
如果您希望您的代碼像多參數分派一樣工作,您將需要實現眾所周知的訪問者模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.