Java向上轉型與向下轉型(子類的物件賦給父類的)
一.定義:
通俗理解向上轉型:
就是子類轉型成父類。
classA
{
}
classBextendsA
{
}
A b=new B();
這個就是向上轉型。
向上轉型可以像下面這條語句這麼簡單:
Shape s =new Circle();
這裡,建立一個Circle物件,並把得到的引用立即賦值給S矇,這樣做看似錯誤(將一種型別賦值給別一種型別);但實際上沒有問題,因為通過繼承,Circle就是一種Shape。因此,編譯器認可這條語句,也就不會產生錯誤資訊。
二.注意事項:
(1)向上轉型的物件的引用呼叫的方法是子類的。
(2)但如果呼叫的方法父類中沒有的話則會報錯。(意思是隻能呼叫子類中過載父類的方法)
(3)父類的引用可以指向子類的物件,但是子類的引用不能指向父類的物件。
java 轉型問題其實並不複雜,只要記住一句話:父類引用指向子類物件。
什麼叫父類引用指向子類物件,且聽我慢慢道來.
從2個名詞開始說起:向上轉型(upcasting) 、向下轉型(downcasting).
舉個例子:有2個類,Father是父類,Son類繼承自Father。
Father f1 = new Son(); // 這就叫 upcasting (向上轉型)
// 現在f1引用指向一個Son物件
Son s1 = (Son)f1; // 這就叫 downcasting (向下轉型)
// 現在f1還是指向Son物件
第2個例子:
Father f2 = new Father();
Son s2 = (Son)f2; // 出錯,子類引用不能指向父類物件
你或許會問,第1個例子中:Son s1 = (Son)f1;問什麼是正確的呢。
很簡單因為f1指向一個子類物件,Father f1 = new Son(); 子類s1引用當然可以指向子類物件了。
而f2 被傳給了一個Father物件,Father f2 = new Father();子類s1引用不能指向父類物件。
總結:
1。父類引用指向子類物件,而子類引用不能指向父類物件。
2。把子類物件直接賦給父類引用叫upcasting向上轉型,向上轉型不用強制轉換。
如:Father f1 = new Son();
3。把指向子類物件的父類引用賦給子類引用叫向下轉型(downcasting),要強制轉換。
如:f1 就是一個指向子類物件的父類引用。把f1賦給子類引用s1即 Son s1 = (Son)f1;
其中f1前面的(Son)必須加上,進行強制轉換。
現在再進一步變化,在父類和子類中同時定義和賦值同名的成員變數name,並試圖輸出該變數的值。
1 public class Father { 2 3 protected String name="父親屬性"; 4 5 public void method() { 6 System.out.println("父類方法,物件型別:" + this.getClass()); 7 } 8 } 9 10 public class Son extends Father { 11 protected String name="兒子屬性"; 12 13 public void method() { 14 System.out.println("子類方法,物件型別:" + this.getClass()); 15 } 16 17 public static void main(String[] args) { 18 Father sample = new Son();//向上轉型 19 System.out.println("呼叫的成員:"+sample.name); 20 } 21 } 22 23 public class Father { 24 25 protected String name="父親屬性"; 26 27 public void method() { 28 System.out.println("父類方法,物件型別:" + this.getClass()); 29 } 30 } 31 32 public class Son extends Father { 33 protected String name="兒子屬性"; 34 35 public void method() { 36 System.out.println("子類方法,物件型別:" + this.getClass()); 37 } 38 39 public static void main(String[] args) { 40 Father sample = new Son();//向上轉型 41 System.out.println("呼叫的成員:"+sample.name); 42 } 43 } 44 45 46 47 48結果3:
呼叫的成員:父親屬性
這個結果表明,子類的物件(由父類的引用handle)呼叫到的是父類的成員變
現在試圖呼叫子類的成員變數name,該怎麼做?最簡單的辦法是將該成員變數封裝成方法getter形式。
[c-sharp] view plaincopyprint?1 public class Father { 2 protected String name = "父親屬性"; 3 public String getName() { 4 return name; 5 } 6 public void method() { 7 System.out.println("父類方法,物件型別:" + this.getClass()); 8 } 9 } 10 11 public class Son extends Father { 12 protected String name="兒子屬性"; 13 14 public String getName() { 15 return name; 16 } 17 18 public void method() { 19 System.out.println("子類方法,物件型別:" + this.getClass()); 20 } 21 22 public static void main(String[] args) { 23 Father sample = new Son();//向上轉型 24 System.out.println("呼叫的成員:"+sample.getName()); 25 } 26 } 27 28 public class Father { 29 protected String name = "父親屬性"; 30 public String getName() { 31 return name; 32 } 33 public void method() { 34 System.out.println("父類方法,物件型別:" + this.getClass()); 35 } 36 } 37 38 public class Son extends Father { 39 protected String name="兒子屬性"; 40 41 public String getName() { 42 return name; 43 } 44 45 public void method() { 46 System.out.println("子類方法,物件型別:" + this.getClass()); 47 } 48 49 public static void main(String[] args) { 50 Father sample = new Son();//向上轉型 51 System.out.println("呼叫的成員:"+sample.getName()); 52 } 53 } 54 55 56 57
結果4:
呼叫的成員:兒子屬性
三.向上轉型的作用:
在父類有多個子類時,利用向上轉型減少重複程式碼量。