Java 淺析三大特性之一多態 之前我們的文章講了Java的封裝和繼承,封裝講的時候,並沒有體現出來封裝的強大之處,反而還要慎用封裝。因為這時的封裝還沒有和多態聯繫到一起,還無法看出向上轉型的厲害之處。 多態,是指同一個行為具有多種的表現形式。同一個方法根據調用對象的不同而產生多種結果。對於Java ...
Java 淺析三大特性之一多態
之前我們的文章講了Java的封裝和繼承,封裝講的時候,並沒有體現出來封裝的強大之處,反而還要慎用封裝。因為這時的封裝還沒有和多態聯繫到一起,還無法看出向上轉型的厲害之處。
多態,是指同一個行為具有多種的表現形式。同一個方法根據調用對象的不同而產生多種結果。對於Java而言,多態就是程式中定義的引用變數,和調用方法的代碼在編譯的時候就決定好了,但引用變數所指向的對象,卻是在運行時才確定的。舉一個很簡單的例子,人要工作。這裡工作是一個方法,但一個作家工作就是寫文章,一個程式員工作卻是寫代碼。工作的執行者不同,工作的內容也不同。這就是一種多態。
多態的實現
對於我們而言,實現多態要如下的準備。
- 繼承
- 方法覆寫
- 向上轉型
對於Java ,則是通過動態綁定來實現。我們先理解一下什麼是動態綁定,才方便後面去利用多態的特性。
動態綁定
綁定是指將一個方法調用同一個方法主體關聯起來。
動態綁定是值在運行時根據對象的類型進行綁定,而與之對應就是靜態綁定,在編譯期就進行綁定,在Java裡面只有final static private 和構造方法是靜態綁定的。
我們已經知道了一般方法的調用是在運行時根據對象的類型進行調用的,換句話說,不管你在代碼里是怎麼寫的,在運行時才會真正決定調用方法的對象是哪個。
實現形式
之前繼承的文章裡面,我們已經知道是可以通過向上轉型將一個子類轉型成父類,那麼我們就可以寫出下麵的代碼
Animal animal = new Dog();
如果Dog覆寫了Animal中的方法,那麼調用這個被覆寫的方法時根據上面的動態綁定的規則,我們就知道實際調用的對象是Dog,那麼執行的也會是Dog類的那個方法。具體的例子如下:
public class Animal {
public void run() {
System.out.println("動物在奔跑");
}
}
public class Cat extends Animal {
@Override
public void run() {
System.out.println("貓在奔跑");
}
}
public class Dog extends Animal{
@Override
public void run() {
System.out.println("狗在奔跑");
}
public static void main(String[] args) {
Animal[] animal = {new Dog(),new Cat()};
animal[0].run();
animal[1].run();
}
}
//運行的結果
狗在奔跑
貓在奔跑
在這個例子裡面,我們可以看到多態的應用,在父類中定義一個通用的run方法,在子類中去實現不同的run方法,然後將子類的對象賦給父類的引用,就可以根據子類的不同 去調用不同的run方法了。這裡面,多態的實現滿足了上面的三點,首先是繼承關係,其次,在子類中覆寫父類的方法,最後,對子類的對象進行向上轉型,產生多態。
多態的好處
我們在上個例子基礎上在添加一段代碼:
public class Log {
public void print(Animal animal) {
System.out.println(new Date().toString());
animal.run();
}
}
//我們將Dog類,修改成下麵這個樣子
public class Dog extends Animal{
@Override
public void run() {
System.out.println("狗在奔跑");
}
public static void main(String[] args) {
Animal[] animal = {new Dog(),new Cat()};
for (Animal item : animal) {
new Log().print(item);
}
}
}
運行的結果如下:
Wed Jul 13 17:07:40 CST 2016
狗在奔跑
Wed Jul 13 17:07:40 CST 2016
貓在奔跑
在上面的例子中,如果我們不採用多態,那麼我們在Log中就要根據不同的對象,生成不同print方法,這樣修改起來異常的麻煩。而採用多態的話,我們只需要在方法中編寫父類的對象調用方法的代碼,但在運行時傳入子類的對象,就會動態綁定到子類上,調用子類實現的方法。這樣做,在添加新的動物類的時候,我們也不用修改我們的print方法,不用改變已經編寫好的代碼,那麼也不會影響已經實現的方法。多態成功的區分開了"改變的事物和未改變的事物"。這給我們編程帶來極大的便利。