在《think of java》中對'向上轉型'有着如下的描述
看完之后很蒙圈,所以自己在網上找了一些描述,並自己做了簡單的總結
簡單的例子
class A{ a.A1; a.A2; 輸出:System.out.println("子類方法1"); System.out.println("父類方法2"); 說明: A a=new B();
|
來自CSDN。通俗易懂。
我們在現實中常常這樣說:這個人會唱歌。在這里,我們並不關心這個人是黑人還是白人,是成人還是小孩,也就是說我們更傾向於使用抽象概念“人”。再例如,麻雀是鳥類的一種(鳥類的子類),而鳥類則是動物中的一種(動物的子類)。我們現實中也經常這樣說:麻雀是鳥。這兩種說法實際上就是所謂的向上轉型,通俗地說就是子類轉型成父類。這也符合Java提倡的面向抽象編程思想。來看下面的代碼:
package a.b;
public class A {
public void a1() {
System.out.println("Superclass");
}
}
A的子類B:
package a.b;
public class B extends A {
public void a1() {
System.out.println("Childrenclass"); //覆蓋父類方法
}
public void b1(){} //B類定義了自己的新方法
}
C類:
package a.b;
public class C {
public static void main(String[] args) {
A a = new B(); //向上轉型
a.a1();
}
}
如果運行C,輸出的是Superclass 還是Childrenclass?不是你原來預期的Superclass,而是Childrenclass。這是因為a實際上指向的是一個子類對象。當然,你不用擔心,Java虛擬機會自動准確地識別出究竟該調用哪個具體的方法。不過,由於向上轉型,a對象會遺失和父類不同的方法,例如b1()。有人可能會提出疑問:這不是多此一舉嗎?我們完全可以這樣寫:
B a = new B();
a.a1();
確實如此!但這樣就喪失了面向抽象的編程特色,降低了可擴展性。其實,不僅僅如此,向上轉型還可以減輕編程工作量。來看下面的顯示器類Monitor:
package a.b;
public class Monitor{
public void displayText() {}
public void displayGraphics() {}
}
液晶顯示器類LCDMonitor是Monitor的子類:
package a.b;
public class LCDMonitor extends Monitor {
public void displayText() {
System.out.println("LCD display text");
}
public void displayGraphics() {
System.out.println("LCD display graphics");
}
}
陰極射線管顯示器類CRTMonitor自然也是Monitor的子類:
package a.b;
public class CRTMonitor extends Monitor {
public void displayText() {
System.out.println("CRT display text");
}
public void displayGraphics() {
System.out.println("CRT display graphics");
}
}
等離子顯示器PlasmaMonitor也是Monitor的子類:
package a.b;
public class PlasmaMonitor extends Monitor {
public void displayText() {
System.out.println("Plasma display text");
}
public void displayGraphics() {
System.out.println("Plasma display graphics");
}
}
現在有一個MyMonitor類。假設沒有向上轉型,MyMonitor類代碼如下:
package a.b;
public class MyMonitor {
public static void main(String[] args) {
run(new LCDMonitor());
run(new CRTMonitor());
run(new PlasmaMonitor());
}
public static void run(LCDMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
public static void run(CRTMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
public static void run(PlasmaMonitor monitor) {
monitor.displayText();
monitor.displayGraphics();
}
}
可能你已經意識到上述代碼有很多重復代碼,而且也不易維護。有了向上轉型,代碼可以更為簡潔:
package a.b;
public class MyMonitor {
public static void main(String[] args) {
run(new LCDMonitor()); //向上轉型
run(new CRTMonitor()); //向上轉型
run(new PlasmaMonitor()); //向上轉型
}
public static void run(Monitor monitor) { //父類實例作為參數
monitor.displayText();
monitor.displayGraphics();
}
}
我們也可以采用接口的方式,例如:
package a.b;
public interface Monitor {
abstract void displayText();
abstract void displayGraphics();
}
將液晶顯示器類LCDMonitor稍作修改:
package a.b;
public class LCDMonitor implements Monitor {
public void displayText() {
System.out.println("LCD display text");
}
public void displayGraphics() {
System.out.println("LCD display graphics");
}
}
CRTMonitor、PlasmaMonitor類的修改方法與LCDMonitor類似,而MyMonitor可以不不作任何修改。
可以看出,向上轉型體現了類的多態性,增強了程序的簡潔性。