面向對象之多態(Java實現)

本文借鑒於csdn,博客園,b站等各大知識分享平台

之前學習了封裝與繼承,封裝就是數據的封裝性(大致理解),繼承就是一個類繼承另一個類的屬性,稱為父子類

多態

多態是面向對象的第三大特性(共三大特性)

求面積,對於不同的圖形有不同的求法。所以說,對於同一種行為,不同的事物可以體現出不同的形態。多態,描述的就是這樣的狀態。

定義:

多態是指同一行為,具有多個不同表現形式

多態的前提:

  1. 繼承或者實現【二選一】
  2. 方法的重寫【意義體現:不重寫,無意義】
  3. 父類引用指向子類對象【格式體現】

格式:

父類類型 變量名 = new 子類對象;
變量名.方法名();

注意:父類類型可以是子類對象繼承的父類,也可以是實現的父接口類型

代碼:

Fu f = new Zi();
f.method();

當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,執行的是子類重寫後方法。

可能會覺得現在暫時的使用似乎沒什麼用處,那麼如何去正確的使用其這也就是接下來所要敘述的,多態的好處
實際開發的過程中,父類類型作為方法形式參數,傳遞子類對象給方法,進行方法的調用,更能體現出多態的擴展性與便利。
定義父類:

public abstract class Animal {
public abstract void eat();
}

定義子類:

class Cat extends Animal {
public void eat() {
System.out.println("吃魚");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨頭");
}
}

定義測試類:

public class Test {
public static void main(String[] args) {
// 多態形式,創建對象
Cat c = new Cat();
Dog d = new Dog();
// 調用showCatEat
showCatEat(c);
// 調用showDogEat
showDogEat(d);
/*
以上兩個方法, 均可以被showAnimalEat(Animal a)方法所替代
而執行效果一致
*/
showAnimalEat(c);
showAnimalEat(d);
}
public static void showCatEat (Cat c){
c.eat();
}
public static void showDogEat (Dog d){
d.eat();
}
public static void showAnimalEat (Animal a){
a.eat();
}
}

由上面的代碼可以看出,showanimaleat方法的animal類型,是cat和dog的父類型,用它去接收子類對象,相當於用0-100去接洽0-10這是絕對可以收下的,因為夫類型肯定是比子類型要大
當eat方法執行的時候,多態規定,執行的是子類重寫的方法,那麼效果自然與showCatEat、showDogEat方法一致,所以showAnimalEat完全可以替代以上兩方法。
不僅僅是替代,在擴展性方面,無論之後再多的子類出現,我們都不需要編寫showXxxEat方法了,直接使用showAnimalEat都可以完成。
所以,多態的好處,體現在,可以使程序編寫的更簡單,並有良好的擴展。

引用類型的轉換

多態的轉型分為向上和向下兩種
向上轉型
向上轉型:多態本身是子類類型向父類類型向上轉換的過程,這個過程是默認的。
當父類引用指向一個子類對象時,便是向上轉型。
使用格式:
父類類型 變量名 = new 子類類型();

向下轉型
向下轉型:父類類型向子類類型向下轉換的過程,這個過程是強制的。

一個已經向上轉型的子類對象,將父類引用轉為子類引用,可以使用強制類型轉換的格式,便是向下轉型。
使用格式: 子類類型 變量名 = (子類類型) 父類變量名;

為什麼要轉型
當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤。也就是說,不能調用子類擁有,而父類沒有的方法。編譯都錯誤,更別說運行了。這也是多態給我們帶來的一點”小麻煩”。所以,想要調用子類特有的方法,必須做向下轉型。

為了避免ClassCastException的發生,Java提供了 instanceof 關鍵字,給引用變量做類型的校驗,格式如下:

變量名 instanceof 數據類型
如果變量屬於該數據類型,返回true。
如果變量不屬於該數據類型,返回false。

實例:
筆記本電腦(laptop)通常具備使用USB設備的功能。在生產時,筆記本都預留了可以插入USB設備的USB接口,但具體是什麼USB設備,筆記本廠商並不關心,只要符合USB規格的設備都可以。
定義USB接口,具備最基本的開啟功能和關閉功能。鼠標和鍵盤要想能在電腦上使用,那麼鼠標和鍵盤也必須遵守USB規範,實現USB接口,否則鼠標和鍵盤的生產出來也無法使用。

分析:
進行描述筆記本類,實現筆記本使用USB鼠標、USB鍵盤

  • USB接口,包含開啟功能、關閉功能
  • 筆記本類,包含運行功能、關機功能、使用USB設備功能
  • 鼠標類,要實現USB接口,並具備點擊的方法
  • 鍵盤類,要實現USB接口,具備敲擊的方法

實現
usb接口:

package cn.qioha.test2Interface;

public interface USB {
    public abstract void on();
    public abstract void off();
}

computer類

package cn.qioha.test2Interface;

public class Computer {
    public void switchOn(){
        System.out.println("打開計算機");
    }
    public void switchOff(){
        System.out.println("關閉計算機");
    }
    public void useDevice(USB usb){
        usb.on();
        if(usb instanceof Mouse){
            ((Mouse) usb) .click();
        }
        else if (usb instanceof Keyboard){
            ((Keyboard) usb).input();
        }
        usb.off();
    }

    public static void main(String[] args) {
        Computer c = new Computer();
        c.switchOn();
        c.useDevice(new Mouse());
        c.useDevice(new Keyboard());
        c.switchOff();
    }
}

keyboard類:

package cn.qioha.test2Interface;

public class Keyboard implements USB{
    @Override
    public void on() {
        System.out.println("開啟鍵盤");
    }

    @Override
    public void off() {
        System.out.println("關閉鍵盤");
    }
    public void input(){
        System.out.println("鍵盤輸入");
    }
}

Mouse類:

package cn.qioha.test2Interface;

public class Mouse implements USB{
    @Override
    public void on() {
        System.out.println("開啟鼠標");
    }

    @Override
    public void off() {
        System.out.println("關閉鼠標");
    }
    public void click(){
        System.out.println("鼠標點擊");
    }
}

ok,大致就實現了,這裡還有很多的不足,接下來的更新我打算就更新問題即可,不再以回顧式樣的去更新博客了,對自己的問題進行一個記錄反而是更好的
多有參考,僅供學習使用,麻煩見諒,侵權我立刪!

Tags: