簡體   English   中英

java 中的動態綁定和覆蓋/重載

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM