1. 程式人生 > >4、面向物件(二)

4、面向物件(二)

1、多型

多型簡介

多型就是事物存在的多種形態,比如你在大街上看見一隻藏獒,你可以說這隻藏獒真凶猛,也可以說這隻狗真凶猛,還可以說這個動物真凶猛,以上三種說法其實都是指的這隻藏獒。
在Java裡面,也是存在多型的,只要全部符合下面這三種情況,就是多型

  • 有繼承
  • 有方法重寫
  • 有父類引用指向子類物件

例如下面程式碼就構成多型

class Animal{
    public int num = 10;
    
    public void eat(){
        System.out.println("動物再吃!");
    }
}

class Cat extends
Animal{ public int num = 20; public void eat(){ System.out.println("貓再吃!"); } } class Animal_Text{ public static void main(String[] args){ Animal m1 = new Cat();// 父親引用指向子類物件 m1.eat(); // 貓在吃 動態繫結和靜態繫結 System.out.println(m1.num); // 10 說明成員變數不存在 } }

靜態繫結和動態繫結

上面程式碼中,a1是Animal型別的一個引用,指向的是其子類Cat的物件,這個就叫做父類引用指向子類物件。程式在編譯的時候a1被看做Animal型別,所以a1.eat()繫結的是Animal類中的eat()方法,這叫做靜態繫結,程式執行時,a1指向的是堆中的Cat物件,而在Cat中對eat()方法進行了重寫,所以在執行階段繫結的是Cat中的eat()方法,這叫做動態繫結

強制型別轉換

上面程式碼中子類向父型別進行轉換,是自動型別轉換,也叫做向上轉型。還有一種情況是父類向子型別轉換,是強制型別轉換,也叫向下轉型。下面的程式碼演示了強制型別轉換

class
Animal{ public int num = 10; public void eat(){ System.out.println("動物再吃!"); } } class Cat extends Animal{ public int num = 20; public void eat(){ System.out.println("貓再吃!"); } //Cat特有的方法. public void move(){ System.out.println("貓走路很輕盈!"); } } class Dog extends Animal{ //重寫 public void eat(){ System.out.println("狗啃骨頭!"); } } class Animal_Text{ public static void main(String[] args){ Animal a1 = new Cat();// 父親引用指向子類物件 //如果要是想執行Cat裡面的move方法該怎麼辦? //只能強制型別轉換,需要加強制型別轉換符 Cat c1 = (Cat)a1; c1.move(); Animal a2 = new Dog(); //向上轉型. //強制型別轉換 //Cat c2 = (Cat)a2; //會報錯 java.lang.ClassCastException } }

instanceof關鍵字

上面的程式碼裡面將一個指向Dog物件的Animal引用a2進行強制轉換成Cat型別時報出了ClassCastException類轉型錯誤,開發中要是想避免這種錯誤需要使用instanceof來判斷一下。

class Animal{
    public int num = 10;
    
    public void eat(){
        System.out.println("動物再吃!");
    }
}

class Cat extends Animal{
    public int num = 20;
    public void eat(){
        System.out.println("貓再吃!");
    }
    
    //Cat特有的方法.
    public void move(){
        System.out.println("貓走路很輕盈!");
    }
}


class Dog extends Animal{

    //重寫
    public void eat(){
        System.out.println("狗啃骨頭!");
    }
}

class Animal_Text{
    public static void main(String[] args){
        Animal a1 = new Cat();// 父親引用指向子類物件
        //如果要是想執行Cat裡面的move方法該怎麼辦?
        //只能強制型別轉換,需要加強制型別轉換符
        Cat c1 = (Cat)a1;
        c1.move();

        Animal a2 = new Dog(); //向上轉型.
        //進行強制型別轉換時,需要先使用instanceof進行判斷,避免ClassCastException
        if (a2 instanceof Cat){
            //強制型別轉換
            Cat c2 = (Cat)a2;
        }else{
            System.out.println("無法進行強制型別轉換");
        }
    }
}

多型的優點

  • 提高了程式的擴充套件性
  • 降低了程式碼之間的耦合
class Car{
    public void run(){
        System.out.println("汽車在行駛!");
    }
}

class Benz extends Car{
    public void run(){
        System.out.println("賓士汽車在跑");
    }
}

class BWM extends Car{
    public void run(){
        System.out.println("寶馬汽車再跑!");
    }
}

class Person{
     /*
    public void drive(Benz bc){
        bc.run();
    }
    賓士汽車壞了,再重新建立一個開寶馬汽車的方法
    public void drive(BMW bm){
        bm.run();
    }
    */

    //上面程式碼擴充套件性太差,每新增加一種品牌的汽車就需要再寫一個方法
    //將引數修改為Car型別,這樣不論增加什麼樣的品牌汽車,都可以呼叫這個方法
    public void driver(Car c){
        c.run();
    }
}

public class Test{
    public static void main(String[] args){
        Person james = new Person();

        //Benz bc = new Benz();
        //james.drive(bc);

        BMW bm = new BMW();    
        james.drive(bm);
    
    }
}