淺談Java多態


多態

多態是同一個行為具有多個不同表現形式或形態的能力。

多態就是同一個接口,使用不同的實例而執行不同操作。

那么怎么理解這句話呢?

我們假設有基類Animal,兩個Animal的派生類Cat和Dog。

我現在有塊廣告牌,想要輸入什么動物就放什么動物的照片?如果沒有多態,我是不是需要不斷地進行判斷?

那么有了多態,我們可以如下實現:

// 創建Animal類
class Animal{
	protected String name;	// 可被子類訪問的name
	public Animal() {
		this.name = "Animal";
	}
	// 封裝
	public String getName() {
		return this.name;
	}
}

class Cat extends Animal{
	Cat(){
		name = "Cat";
	}
}

class Dog extends Animal{
	Dog(){
		name = "Dog";
	}
}

public class Test {
	static public void board(Animal s) {		
		System.out.println(s.getName());
	}
	
	public static void main(String[] args) {
		Animal animal = new Animal();	//創建Animal對象
		Animal cat = new Cat();			//創建Cat對象
		Animal dog = new Dog();			//創建Dog對象
		// 三塊廣告牌
		board(animal);
		board(cat);
		board(dog);
		
	}
}

// output
// Animal
// Cat
// Dog

從這個代碼和結果,我們就已經可以看出,多態有什么用了!那么,要怎么實現多態呢!

多態存在的三個必要條件

  • 繼承
  • 重寫
  • 基類引用指向派生類對象(引用還是指向基類)

比如

Parent p = new Child();

​ 當使用多態方式調用方法時,首先檢查基類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去調用派生類的同名方法。

重載(Overload)與重寫(Override)

多態中重寫的基本規則

  1. 參數必須要一樣,且返回類型必須兼容

    重寫是派生類對基類的允許訪問的方法的實現過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!

    基類定義出其他的程序代碼要如何使用方法。不管基類使用了哪種參數,覆蓋此方法的派生類也一定要使用相同的參數。同樣,不論基類聲明的返回類型是什么,派生類必須要聲明返回一樣的類型或該類型的派生類。要記得,派生類對象必須保證可以執行基類的一切。

  2. 不能降低方法存取的極限

    簡而言之,方法和變量的存取權必須相同或者更為開放。

    例如不能把public的方法降低為private。

  3. 基類的成員方法只能被它的派生類重寫。

  4. 聲明為 final 的方法不能被重寫。

  5. 聲明為 static 的方法不能被重寫,但是能夠被再次聲明。

  6. 構造方法不能被重寫。

  7. 如果不能繼承一個方法,那么它一定不能被重寫

  8. 當需要在派生類中調用基類的被重寫方法時,要使用 super 關鍵字。

    class Animal{
       public void move(){
          System.out.println("動物可以移動");
       }
    }
     
    class Dog extends Animal{
       public void move(){
          super.move(); // 應用super類的方法
          System.out.println("狗可以跑和走");
       }
    }
     
    public class TestDog{
       public static void main(String args[]){
     
          Animal b = new Dog(); // Dog 對象
          b.move(); //執行 Dog類的方法
     
       }
    }
    
    
    //編譯結果如下
    >>>動物可以移動
    >>>狗可以跑和走
    

重載

重載的意義時同一個類里,兩個方法的名稱相同,但參數不同。

所以,重載和多態沒有半毛錢關系!

重載可以有同一方法的多個不同參數版本以便調用。比如某個方法需要int,調用方就需要把double轉成int然后才能調用。如果有個重載版的方法取用double參數,這樣調用就簡單多了。

因為重載方法不需要滿足定義在基類的多態合約,所以擴展起來比較方便。

重載最常用的地方就是構造器的重載。

原則

  1. 返回類型可以不同

    可以任意改變重載方法的返回類型,只要所有的覆蓋使用不同參數即可。

  2. 不能只改變返回類型

    如果只有返回類型改變但參數一樣,編譯器不會通過編譯。也就是說,被重載的方法必須改變參數列表(參數個數或類型不一樣);

    結合前兩條,無法以返回值類型作為重載函數的區分標准。

  3. 可以更改存儲權限

    可以任意地設定重載方法的存儲權限。

  4. 方法能夠在同一個類中或者在一個派生類中被重載。

public class Overloading {
    public int test(){
        System.out.println("test1");
        return 1;
    }
 
    public void test(int a){
        System.out.println("test2");
    }   
 
    //以下兩個參數類型順序不同
    public String test(int a,String s){
        System.out.println("test3");
        return "returntest3";
    }   
 
    public String test(String s,int a){
        System.out.println("test4");
        return "returntest4";
    }   
 
    public static void main(String[] args){
        Overloading o = new Overloading();
        System.out.println(o.test());
        o.test(1);
        System.out.println(o.test(1,"test3"));
        System.out.println(o.test("test4",1));
    }
}

重寫與重載之間的區別

區別點 重載方法 重寫方法
參數列表 必須修改 一定不能修改
返回類型 可以修改 一定不能修改
異常 可以修改 可以減少或刪除,一定不能拋出新的或者更廣的異常
訪問 可以修改 一定不能做更嚴格的限制(可以降低限制)

總結

方法的重寫(Overriding)和重載(Overloading)是java多態性的不同表現,重寫是基類與派生類之間多態性的一種表現,重載可以理解成多態的具體表現形式。

  • (1)方法重載是一個類中定義了多個方法名相同,而他們的參數的數量不同或數量相同而類型和次序不同,則稱為方法的重載(Overloading)。
  • (2)方法重寫是在派生類存在方法與基類的方法的名字相同,而且參數的個數與類型一樣,返回值也一樣的方法,就稱為重寫(Overriding)。
  • (3)方法重載是一個類的多態性表現,而方法重寫是派生類與基類的一種多態性表現。

附一張網圖

重載與重寫

多態成員訪問的特點

Parent p = new Child();

成員變量

編譯看左邊(基類),運行看左邊(基類);無論如何都是訪問基類的成員變量。

成員方法

編譯看左邊(基類),運行看右邊(派生類),動態綁定。

Static方法

編譯看左邊(基類),運行看左邊(基類)。

只有非靜態的成員方法,編譯看左邊,運行看右邊。

這樣,我們也可以得出多態的局限:

不能使用派生類特有的成員屬性和派生類特有的成員方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM