簡體   English   中英

上載Java中的子類引用

[英]Upcasting a subclass reference in Java

我在Bruce Eckel撰寫的《 Java思維第四版 》中進行以下練習:

練習16:(2)創建一個名為Amphibian的類。 從此繼承一個名為Frog的類。 在基類中放置適當的方法。 在main()中,創建Frog並將其向上轉換為兩棲動物,並演示所有方法仍然有效。

Frog f = new Frog();什么區別Frog f = new Frog(); Amphibian f = new Frog(); 在:

class Amphibian {
    void go() { System.out.println("go"); }
    void stop() { System.out.println("stop!"); }
}

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
}

public class EFrog {
    public static void main(String[] args) {
        Frog f = new Frog();
        f.go();
    }
}

但是我不明白Frog f = new Frog();和Frog有什么區別? 和兩棲動物f = new Frog();

要了解它們之間的區別,讓我們在Frog中添加另一種不在Amphibian

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void come() { System.out.println("come"); }
}

現在讓我們看一下有什么區別:

public class EFrog {
    public static void main(String[] args) {
        Frog f = new Frog();
        f.go();
        f.come();
        Amphibian a = f;
        a.come();//this won't compile
    }
}

底線。 FrogAmphibian所以Frog可以做Amphibian可以做的任何事情。 Amphibian不是Frog所以Amphibian不能做Frog能做的一切。

當您說Amphibian a = new Frog() ,您是在編程接口(不是java接口,而是接口的一般含義)。 當您說Frog f = new Frog()您正在編程實現。

現在來看書要求您嘗試的實際問題:

在main()中,創建一個Frog並將其向上轉換為兩棲動物,並演示所有方法仍然有效。

public class EFrog {
        public static void main(String[] args) {
            Frog f = new Frog();
            Amphibian g = (Amphibian)f;//this is an upcast
            g.go(); //okay since Amphibian can go
            g.come();//not okay since Amphibian can't come                
        }
    }

我不認為您要問的是upcasting的用途,但由於標題已經由其他人編輯,為什么不回答呢? 上載在某些情況下很有用,例如明確調用重載方法的特殊形式。 有關其他詳細信息,請參見此答案。

在這個簡單的程序中,實際上沒有區別。 但是,如果您有Amphibian f ,它可以指代任何兩棲動物,而不僅僅是Frog 您仍然使用Amphibian提供的所有方法,即使它是Frog的實例也是如此。請參閱什么是多態性,其用途以及如何使用? 用於描述多態性。

Frog f = new Frog();什么區別Frog f = new Frog(); Amphibian f = new Frog();

從您的示例中我們可以看到Frog繼承了Amphibian 因此,任何聲明為Amphibian類型的變量都可以始終在您的案例Frog存儲具有超類為Amphibian的對象的實例。 至於示例代碼,沒有區別。

但是,在您的示例中找不到兩者之間的細微差別。 考慮以下:

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void croak(){ System.out.println("croak");} //Added this extra line
}

現在,如果您將Frog實例存儲為

Amphibian f = new Frog();
f.croak(); //This will not work.

這是行不通的,因為JVM將f視為Amphibian類型,並且在Amphibian類中沒有croak方法。 因此會引發錯誤。 但是,如果您將其存儲為:

Frog f = new Frog();
f.croak(); //This will work.

這是工作,因為JVM認為˚F類型Frog和類Frog具有方法croak

當然,您可以通過將f強制轉換為Frog來使前面的案例工作:

Amphibian f = new Frog();
((Frog)f).croak(); //This will work.

這就是我們所說的多態性。 那是很多形狀。 同一對象的許多形狀。 如您所知,同一對象可以稱為Frog,也可以稱為兩棲動物。 當引用是兩棲動物時,原始對象仍然是Frog,因此將調用覆蓋的方法。

要了解兩者之間的區別,您可以將方法jump()添加到Frog(但不能將其添加到基類Amphibian:

class Amphibian {
    void go() { System.out.println("go"); }
    void stop() { System.out.println("stop!"); }
}

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void jump() { System.out.println("jump!"); }
}

public class EFrog {
    public static void main(String[] args) {
        Frog f = new Frog();
        f.go();
        f.jump(); // works
        Amphibian a = new Frog();
        a.jump(); // will not compile!
    }
}

這是簡單的如果您使用如下

Frog f = new Frog();

這樣就無法將其轉換為其他任何類型。 但是,您可以調用所有Frog方法。

但是如果你像下面這樣使用

Amphibian f = new Frog();

您仍然可以通過簡單的操作將對象更改為其他兩棲動物,而無需更改其引用。

f = new SomeOtherAmphibian();

這種編碼方式非常流行,被稱為對基類或接口進行編碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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