多態的理解


什么是多態

定義:不同類的對象對同一個消息作出不同的響應。

解釋:見如下代碼

  不同類的對象:子類cat和子類dog

  同一個消息:調用eat()方法

  不同的響應:分別為 cat eat 和 dog eat

//父類Animal
public
class Animal { public void eat(){ System.out.println("animal eat"); } } //子類Cat public class Cat extends Animal{ @Override public void eat() { System.out.println("cat eat"); } } //子類Dog public class Dog extends Animal{ @Override public void eat() { System.out.println("dog eat"); } }

//測試
public class TestController {

public static void main(String[] args) {
Animal animal1 = new Cat();
Animal animal2 = new Dog();
animal1.eat();
animal2.eat();
}

}

結果:

cat eat
dog eat

由此引出多態存在的三個條件

多態存在的三個條件

1.有繼承關系

Cat和Dog繼承Animal

2.子類重寫父類的方法

Cat和Dog重寫父類Animal的eat方法

3.父類的引用變量指向子類對象

Animal animal1 = new Cat();
Animal animal2 = new Dog();

多態的作用

消除類型之間的耦合關系,即解耦。

舉例:

你定義了一個接口,功能是存儲文件。定義了一個下載工具類用來保存下載的文件。

//接口:存儲文件
public interface saveFile {
    void save(File file);
}

//下載工具類,有一方法為將下載的文件存儲下來(調用上述接口)
public class DownLoadTools {
    saveFile saveFile;
    public void downLoad(File file){
        saveFile.save(file);
    }
   public void setDisk(saveFile saveFile){
     this.saveFile = saveFile;
  } }

別人寫了兩個實現類,分別將文件存儲在U盤和硬盤中。

//u盤存儲
public
class UDisk implements saveFile{ @Override public void save(File file) { System.out.println("u盤存儲"); } }
//硬盤存儲
public class HardDisk implements saveFile{ @Override public void save(File file) { System.out.println("硬盤存儲"); } }
//測試
public class Test {
    public static void main(String[] args){
        DownLoadTools downLoadTools = new DownLoadTools();
        //文件存儲到U盤中
        downLoadTools.setSaveFile(new UDisk());
        downLoadTools.downLoad(new File(""));
        //文件存儲到硬盤中
        downLoadTools.setSaveFile(new HardDisk());
        downLoadTools.downLoad(new File(""));
    }
}

結果:

u盤存儲
硬盤存儲

此時如果需要將下載文件存儲到CD中,只需要定義一個CDDisk實現類實現saveFile接口,無需更改downLoadTools下載工具類,這樣downLoadTools類就不依賴於任何具體的類,這樣就解除了與其他類之間的耦合性;

//CD存儲
public class CDDisk implements saveFile{
    @Override
    public void save(File file) {
        System.out.println("CD存儲");
    }
}

//測試
public class Test {
    public static void main(String[] args){
        DownLoadTools downLoadTools = new DownLoadTools();
        //文件存儲到U盤中
        downLoadTools.setSaveFile(new UDisk());
        downLoadTools.downLoad(new File(""));
        //文件存儲到硬盤中
        downLoadTools.setSaveFile(new HardDisk());
        downLoadTools.downLoad(new File(""));
        //文件存儲到CD中
        downLoadTools.setSaveFile(new CDDisk());
        downLoadTools.downLoad(new File(""));
    }
}

結果:

u盤存儲
硬盤存儲
CD存儲

補充說明1:只要一個方法操作的是類而非接口,那么你只能使用這個類及其子類。如果你想要將這個方法應用於不在此繼承結構中的某個類,那么你就觸霉頭了。接口可以在很大程度上放寬這種限制(如上述的saveFile接口),因此,他使我們可以編寫可復用性更好的代碼。——引用《thinking in java》的某一些話。

補充說明2:簡單地說就是,沒有多態,那么等號左邊是啥右邊就得是啥,這就叫耦合,有了多態,左邊是父類(或者接口),右邊是子類(或實現類),我只管調用父類(或者接口)里面的方法就是了,至於你子類(實現類)怎么去實現,那是你的事,你要修改一下實現,你只管去把子類(實現類)換掉,我這邊一行代碼都不用變,這就解耦了。

多態用在什么地方?

1.用在方法的參數中

情景:一個人養了一只寵物,現在調用person的keepPet(參數1)方法需要知道是什么寵物在吃飯

參數1給的是父類Animal的話,那么無論你后來需要養Lion,Tiger,Panda等等,都可以直接繼承父類Animal,而Person的keepPet(參數1)方法不需要改變

若參數1給的是具體的Cat,Dog,Lion等等,那么你養了幾只寵物,就需要寫幾個keepPet()方法,如keepPet(Cat cat),keepPet(Dog dog),keepPet(Lion lion)等。

public class Person {
  //參數給的是父類Animal,那么調用的時候傳參就可以是父類Animal的任意子類對象
public void keepPet(Animal animal){ animal.eat(); } } //父類Animal public class Animal { public void eat(){ System.out.println("animal eat"); } } //子類cat public class Cat extends Animal{ @Override public void eat() { System.out.println("cat eat"); } } //子類dog public class Dog extends Animal{ @Override public void eat() { System.out.println("dog eat"); } }

//測試
public class TestController {

public static void main(String[] args) {
Animal animal1 = new Cat();
Animal animal2 = new Dog();
Person person = new Person();
person.keepPet(animal1);
person.keepPet(animal2);
}

}

結果:

cat eat

dog eat

2.用在方法的返回類型中

前面的cat對象和dog對象都是直接new()的,現在設計一個工廠類,專門生產Animal

//以前
Animal animal1 = new Cat(); Animal animal2 = new Dog(); Person person = new Person(); person.keepPet(animal1); person.keepPet(animal2);
//現在
Animal animal1 = AnimalFactory.animalFactory("cat"); Animal animal2 = AnimalFactory.animalFactory("dog"); Person person = new Person(); person.keepPet(animal1); person.keepPet(animal2);
//工廠類方法,返回值類型是父類Animal,那么返回值就可以是Animal的所有的子類
public
class AnimalFactory { public static Animal animalFactory(String animalName){ if(animalName.equals("cat")){ return new Cat(); }else if(animalName.equals("dog")){ return new Dog(); }else{ System.out.println("暫無該種動物"); return null; } } }

這實際上是設計模式中的工廠模式,當然如果類是一個完全獨立的類,無相似的類,那么直接new()就行了。

 


免責聲明!

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



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