一文掌握JAVA 物件導向之多型

2022-06-15 14:01:42
本篇文章給大家帶來了關於的相關知識,其中主要介紹了關於多型的相關問題,多型是物件導向程式設計的一個重要特徵,指向同一個實體同時具有多種形式,指的是物件的多種形態,下面一起來看一下,希望對大家有幫助。

推薦學習:《》

1. 概念

多型是物件導向程式設計(OOP)的一個重要特徵,指同一個實體同時具有多種形式,即同一個物件,在不同時刻,代表的物件不一樣,指的是物件的多種形態。

可以把不同的子類物件都當作父類別來看,進而遮蔽不同子類物件之間的差異,寫出通用的程式碼,做出通用的程式設計,統一呼叫標準。

比如,你的女盆友讓你買點水果回來,不管買回來的是蘋果還是西瓜,只要是水果就行,這個就是生活中多型的體現

再比如,小貓、小狗、小豬我們可以把他們都歸納成小動物,每種小動物都需要吃東西,所以我們可以統一設定他們都必須吃,但是每種小動物的習性不一樣,那這個就可以設定成小動物自己特有的功能,多型物件只能呼叫父類別中定義子類中重寫的功能,並不能呼叫子類的特有功能,這樣就實現了程式碼的統一

2 . 特點

  1. 多型的前提1:是繼承
  2. 多型的前提2:要有方法的重寫
  3. 父類別參照指向子類物件,如:Animal a = new Cat();
  4. 多型中,編譯看左邊,執行看右邊
    在這裡插入圖片描述

3. 練習:多型入門案例

建立包: cn.tedu.oop
建立類: TestDemo.java

package cn.tedu.oop2;/*本類用作多型的入門案例*/public class TestDemo {
    public static void main(String[] args) {
        //6.建立「純純的」物件用於測試
        Animal a = new Animal();
        Cat c = new Cat();
        Dog d = new Dog();
        a.eat();//小動物Animal吃啥都行~呼叫的是父類別自己的功能
        c.eat();//小貓愛吃小魚乾~呼叫的是子類重寫後的功能
        d.eat();//小狗愛吃肉骨頭~呼叫的是子類重寫後的功能
        /*2.父類別物件不可以使用子類的特有功能*/
        //a.jump();//報錯,Animal類裡並沒有這個方法
        //a.run();//報錯,Animal類裡並沒有這個方法
        c.jump();//小貓Cat跳的老高啦~,子類可以呼叫自己的功能
        d.run();//小狗Dog跑的老快啦~,子類可以呼叫自己的功能

        //7.建立多型物件進行測試
        /*3.口訣1:父類別參照指向子類物件
        * 解釋:建立出來的子類物件的地址值,交給父類別型別的參照型別變數來儲存*/
        Animal a2 = new Cat();//Cat類物件的地址值交給父類別型變數a2來儲存
        Animal a3 = new Dog();//Dog類物件的地址值交給父類別型變數a3來儲存
        //8.測試多型物件
        /*4.口訣2:編譯看左邊,執行看右邊
        * 解釋:必須要在父類別定義這個方法,才能通過編譯,把多型物件看作是父類別型別
        *      必須要在子類重寫這個方法,才能滿足多型,實際幹活的是子類*/
        a2.eat();//小貓愛吃小魚乾~,多型物件使用的是父類別的定義,子類的方法體
    }}/*1.多型的前提:繼承+重寫*///1.建立父類別class Animal{
    //3.建立父類別的普通方法
    public void eat(){
        System.out.println("小動物Animal吃啥都行~");
    }}//2.1建立子類1class Cat extends Animal{
    //4.1新增重寫的方法
    public void eat(){
        System.out.println("小貓愛吃小魚乾~");
    }
    //5.1新增子類的特有功能
    public void jump(){
        System.out.println("小貓Cat跳的老高啦~");
    }}//2.2建立子類2class Dog extends Animal{
    //4.2新增重寫的方法
    @Override
    public void eat(){
        System.out.println("小狗愛吃肉骨頭~");
    }
    //5.2新增子類的特有功能
    public void run(){
        System.out.println("小狗Dog跑的老快啦~");
    }}

4. 多型的好處

  1. 多型可以讓我們不用關心某個物件到底具體是什麼型別,就可以使用該物件的某些方法
  2. 提高了程式的可延伸性和可維護性

5. 多型的使用

前提:多型物件把自己看做是父類別型別

  1. 成員變數: 使用的是父類別的
  2. 成員方法: 由於存在重寫現象,所以使用的是子類的
  3. 靜態成員: 隨著類的載入而載入,誰呼叫就返回誰的

6. 練習:多型成員使用測試

建立包: cn.tedu.oop
建立類: TestDemo2.java

package cn.tedu.oop2;/*本類用於測試多型成員的使用情況*/public class TestDemo2 {
    public static void main(String[] args) {
        //7.建立純純的子類物件
        Dog2 d = new Dog2();
        System.out.println(d.sum);//20,子類自己的屬性
        d.eat();//小狗愛吃肉包子,子類自己的方法

        //8.建立多型物件
        /*口訣1:父類別參照指向子類物件*/
        /*口訣2:編譯(儲存)看左邊,執行(效果)看右邊*/
        Animal2 a = new Dog2();
        /*多型中,成員變數使用的是父類別的*/
        System.out.println(a.sum);//10
        /*多型中,方法的宣告使用的是父類別的,方法體使用的是子類的*/
        a.eat();//小狗愛吃肉包子
        /*多型中,呼叫的靜態方法是父類別的,因為多型物件把自己看作是父類別型別
        * 直接使用父類別中的靜態資源*/
        a.play();//沒有提示,玩啥都行~
        Animal2.play();
    }}//1.建立父類別class Animal2{
    //3.建立父類別的成員變數
    int sum = 10;
    //4.建立父類別的普通方法
    public void eat(){
        System.out.println("吃啥都行~");
    }
    //9.1定義父類別的靜態方法play
    public static void play(){
        System.out.println("玩啥都行~");
    }}//2.建立子類class Dog2 extends Animal2{
    //5.定義子類的成員變數
    int sum = 20;
    //6.重寫父類別的方法
    @Override
    public void eat(){
        System.out.println("小狗愛吃肉包子");
    }
    //9.2建立子類的靜態方法play
    //@Override
    /*這不是一個重寫的方法,只是恰巧在兩個類中出現了一模一樣的兩個靜態方法
    * 靜態方法屬於類資源,只有一份,不存在重寫的現象
    * 在哪個類裡定義,就作為哪個類的資源使用*/
    public static void play(){
        System.out.println("小狗喜歡玩皮球~");
    }}

7 拓展

7.1 設計汽車綜合案例

建立包: cn.tedu.oopexec
建立類: DesignCar.java

package cn.tedu.oop2;/*本類用於完成汽車設計案例*/public class DesignCar {
    public static void main(String[] args) {
        //9.建立一個純純的父類別物件進行測試
        Car c = new Car();
        System.out.println(c.getColor());//null
        c.start();
        c.stop();
        //c.swim();//報錯,父類別物件不可以呼叫子類的特有功能

        //10.建立純純的子類物件做測試
        BMW b = new BMW();
        System.out.println(b.color);//五彩斑斕的黑
        System.out.println(b.getColor());//null
        b.start();//都讓開,我的車要起飛啦~
        b.stop();//唉呀媽呀熄火了~

        //11.建立多型物件進行測試
        Car c2 = new TSL();
        //System.out.println(c2.color);
        System.out.println(c2.getColor());
        c2.stop();
        c2.start();
        //c2.swim();
    }}//1.通過分析,抽象形成一個汽車類class Car{
    //2.定義並封裝汽車類的屬性--成員變數
    private String brand;//品牌
    private String color;//顏色
    private int id;//編號
    private double price;//價格

    //3.定義功能
    public void start(){
        System.out.println("我的小車車啟動啦~");
    }
    public void stop(){
        System.out.println("唉呀媽呀熄火了~");
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }}//4.建立子類class BMW extends Car{
    String color = "五彩斑斕的黑";
    //5.重寫父類別的方法
    @Override
    public void start(){
        System.out.println("都讓開,我的車要起飛啦~");
    }}//6.建立子類2class TSL extends Car{
    //7.重寫父類別的方法
    @Override
    public void stop(){
        System.out.println("唉呀媽,怎麼停不下來呢");
    }
    //8.新增子類的特有功能
    public void swim(){
        System.out.println("沒想到吧,我還是個潛水艇");
    }}

7.2 多型為了統一呼叫標準

package cn.tedu.oop2;public class TestFruit {
    public static void main(String[] args) {
        Fruit f = new Fruit();
        Apple a = new Apple();
        Orange o = new Orange();
        get(f);
        get(a);
        get(o);
    }
    //只需要建立一個方法,就可以執行截然不同的效果
    //忽略子類物件的差異統一看作父類別型別
    public static void get(Fruit f){
        f.clean();
    }}class Fruit{
    public void clean(){
        System.out.println("水果要洗洗再吃");
    }}class Apple extends Fruit{
    @Override
    public void clean(){
        System.out.println("蘋果需要削皮");
    }}class Orange extends Fruit{
    @Override
    public void clean(){
        System.out.println("橙子需要剝皮");
    }}

7.3 靜態變數和範例變數的區別

在語法定義上的區別:靜態變數前要加static關鍵字,而範例變數前則不加。
在程式執行時的區別:範例變數屬於某個物件的屬性,必須建立了範例物件,其中的範例變數才會被分配空間,才能使用這個範例變數。靜態變數不屬於某個範例物件,而是屬於類,所以也稱為類變數,只要程式載入了類的位元組碼,不用建立任何範例物件,靜態變數就會被分配空間,靜態變數就可以被使用了。總之,範例變數必須建立物件後才可以通過這個物件來使用,靜態變數則可以直接使用類名來參照。

7.4 向上轉型和向下轉型

在JAVA中,繼承是一個重要的特徵,通過extends關鍵字,子類可以複用父類別的功能,如果父類別不能滿足當前子類的需求,則子類可以重寫父類別中的方法來加以擴充套件。
那麼在這個過程中就存在著多型的應用。存在著兩種轉型方式,分別是:向上轉型和向下轉型。
向上轉型:可以把不同的子類物件都當作父類別來看,進而遮蔽不同子類物件之間的差異,寫出通用的程式碼,做出通用的程式設計,統一呼叫標準。
比如:父類別Parent,子類Child
父類別的參照指向子類物件:Parent p=new Child();
說明:向上轉型時,子類物件當成父類別物件,只能呼叫父類別的功能,如果子類重寫了父類別中宣告過的方法,方法體執行的就是子類重過後的功能。但是此時物件是把自己看做是父類別型別的,所以其他資源使用的還是父類別型的。
比如:花木蘭替父從軍,大家都把花木蘭看做她爸,但是實際從軍的是花木蘭,而且,花木蘭只能做她爸能做的事,在軍營裡是不可以化妝的。

向下轉型(較少):子類的參照的指向子類物件,過程中必須要採取到強制轉型。這個是之前向上造型過的子類物件仍然想執行子類的特有功能,所以需要重新恢復成子類物件
Parent p = new Child();//向上轉型,此時,p是Parent型別
Child c = (Child)p;//此時,把Parent型別的p轉成小型別Child
其實,相當於建立了一個子類物件一樣,可以用父類別的,也可以用自己的
說明:向下轉型時,是為了方便使用子類的特殊方法,也就是說當子類方法做了功能拓展,就可以直接使用子類功能。
比如:花木蘭打仗結束,就不需要再看做是她爸了,就可以」對鏡貼花黃」了

推薦學習:《》

以上就是一文掌握JAVA 物件導向之多型的詳細內容,更多請關注TW511.COM其它相關文章!