上下轉型
首先,定義一個父類Person
// 父類
class Person {public void run(){System.out.println("person 中的 run");}public void eat(){System.out.println("Person 中的 eat");}}
接著定義一個繼承自父類的子類Student:
// 子類
class Student extends Person {// 重回了父類中的run方法@Overridepublic void run() {System.out.println("Student 中的 run");;}// 父類中沒有的子類特有的方法public void study(){System.out.println("Student 中獨有的study");}
}
ok, 現在開始說明什么是向上轉型和向下轉型:
public class homework11 {public static void main(String[] args) {// 向上轉型,子 -> 父, p1實際上仍然是一個Student方法,可以通過p1.getClass()查看,但是只能調用Person公開的方法Person p1 = new Student();p1.run(); // run是p1公開的方法,所以可以調用,但是記住調用的是子類中的run,因為p1實際上就是一個Student類p1.eat(); // 調用子類中的eat,子類中沒有重寫該方法,雖然結果是“Person 中的 eat”,但是仍然是調用的子類中的該方法// p1.study() // 報錯,只能調用父類中已經聲明了的方法// 向下轉型// 報錯,父類對象不能隱式的轉換成子類,要想轉換必須顯示的聲明,這相當于告訴編譯器我就是故意的,我愿意承擔由此導致的問題// Student s1 = new Person();// Student s1 = (Student) new Person(); // 仍然報錯,因為這里匿名創建的new Person() 對象并不是Student類型// 乍一看跟上面一樣是將Person類轉成了Student,但是并沒有報錯,因為這里的p2實際上是一個Student類,因為p2是Student向上轉型得到的Person p2 = new Student();Student s2 = (Student) p2; // 這里又轉回去了,這沒啥好說的,相當于 Student s2=new Student();}
}
關于多態
上面的向上轉型就是多態的過程,表現為雖然都是Person類型但是實際調用的確實不同的子類自己重新重寫的方法。最典型的應用就是函數的參數是父類,傳進來的是不同的子類,這樣函數內部調用父類的方法時實際運行的是子類重構過的方法。
為了方便說明,這里再定義一個繼承自上面Person類的Teacher類:
public class Teacher extends Person{@Overridepublic void run() {System.out.println("Teacher 中的run");;}
}
ok,具體使用時是這樣的:
public class homework11 {static void f(Person pp){pp.run();}public static void main(String[] args) {Person p1 = new Student();Person p2 = new Teacher();f(p1);// 調用Student類中的run方法f(p2); // 調用Teacher中的run方法}
}
這種操作的優點就是,雖然f()中的代碼已經寫死了,但是實際運行過成中具體調用的方法仍然是可以根據傳進來的子類的不同而發生改變的!