[英]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
}
}
底線。 Frog
是Amphibian
所以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.