Java多態

關於多態的一段代碼

public class test {
    public static void main(String[] args) {
        show(new Cat());  // 以 Cat 對象調用 show 方法
        show(new Dog());  // 以 Dog 對象調用 show 方法

        Animal a = new Cat();  // 向上轉型
        a.eat();               // 調用的是 Cat 的 eat
        Cat c = (Cat) a;        // 向下轉型
        c.work();        // 調用的是 Cat 的 work
    }

    public static void show(Animal a) {
        a.eat();
        // 類型判斷
        if (a instanceof Cat) {  // 貓作的事情
            Cat c = (Cat) a;
            c.work();
        } else if (a instanceof Dog) { // 狗作的事情
            Dog c = (Dog) a;
            c.work();
        }
    }
}

abstract class Animal {
    abstract void eat();
}

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

    public void work() {
        System.out.println("抓老鼠");
    }
}

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

    public void work() {
        System.out.println("看家");
    }
}

輸出結果:java

吃魚
抓老鼠
吃骨頭
看家
吃魚
抓老鼠

虛函數

虛函數的存在是爲了多態。編程

Java 中其實沒有虛函數的概念,它的普通函數就至關於 C++ 的虛函數,動態綁定是Java的默認行爲。若是 Java 中不但願某個函數具備虛函數特性,能夠加上 final 關鍵字變成非虛函數。函數

重寫

Employee.java代碼this

/* 文件名 : Employee.java */
public class Employee {
    private String name;
    private String address;
    private int number;

    public Employee(String name, String address, int number) {
        System.out.println("Employee 構造函數");
        this.name = name;
        this.address = address;
        this.number = number;
    }

    public void mailCheck() {
        System.out.println("郵寄支票給: " + this.name
                + " " + this.address);
    }

    public String toString() {
        return name + " " + address + " " + number;
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String newAddress) {
        address = newAddress;
    }

    public int getNumber() {
        return number;
    }
}

假設下面的類繼承Employee類spa

/* 文件名 : Salary.java */
public class Salary extends Employee {
    private double salary; // 整年工資

    public Salary(String name, String address, int number, double salary) {
        super(name, address, number);
        setSalary(salary);
    }

    public void mailCheck() {
        System.out.println("Salary 類的 mailCheck 方法 ");
        System.out.println("郵寄支票給:" + getName()
                + " ,工資爲:" + salary);
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double newSalary) {
        if (newSalary >= 0.0) {
            salary = newSalary;
        }
    }

    public double computePay() {
        System.out.println("計算工資,付給:" + getName());
        return salary / 52;
    }
}

VirtualDemo.java代碼code

/* 文件名 : VirtualDemo.java */
public class VirtualDemo {
    public static void main(String[] args) {
        Salary s = new Salary("員工 A", "北京", 3, 3600.00);
        Employee e = new Salary("員工 B", "上海", 2, 2400.00);
        System.out.println("使用 Salary 的引用調用 mailCheck -- ");
        s.mailCheck();
        System.out.println("\n使用 Employee 的引用調用 mailCheck--");
        e.mailCheck();
    }
}

運行結果:對象

Employee 構造函數
Employee 構造函數
使用 Salary 的引用調用 mailCheck -- 
Salary 類的 mailCheck 方法 
郵寄支票給:員工 A ,工資爲:3600.0

使用 Employee 的引用調用 mailCheck--
Salary 類的 mailCheck 方法 
郵寄支票給:員工 B ,工資爲:2400.0

多態的實現

  • 重寫
  • 藉口
  • 抽象類和抽象方法

多態的分類

多態通常分爲兩種:重寫式多態和重載式多態。繼承

重載式多態,也叫編譯時多態。也就是說這種多態再編譯時已經肯定好了。重載你們都知道,方法名相同而參數列表不一樣的一組方法就是重載。在調用這種重載的方法時,經過傳入不一樣的參數最後獲得不一樣的結果。接口

可是這裏是有歧義的,有的人以爲不該該把重載也算做多態。由於不少人對多態的理解是:程序中定義的引用變量所指向的具體類型和經過該引用變量發出的方法調用在編程時並不肯定,而是在程序運行期間才肯定,這種狀況叫作多態。 這個定義中描述的就是咱們的第二種多態—重寫式多態。而且,重載式多態並非面向對象編程特有的,而多態倒是面向對象三大特性之一(若是我說的不對,記得告訴我。。)。get

我以爲你們也沒有必要在定義上去深究這些,個人理解是:同一個行爲具備多個不一樣表現形式或形態的能力就是多態,因此我認爲重載也是一種多態,若是你不一樣意這種觀點,我也接受。

重寫式多態,也叫運行時多態。這種多態經過動態綁定(dynamic binding)技術來實現,是指在執行期間判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。也就是說,只有程序運行起來,你才知道調用的是哪一個子類的方法。 這種多態經過函數的重寫以及向上轉型來實現,咱們上面代碼中的例子就是一個完整的重寫式多態。咱們接下來說的全部多態都是重寫式多態,由於它纔是面向對象編程中真正的多態。

JAVA – 虛函數、抽象函數、抽象類、接口

1. Java 虛函數

虛函數的存在是爲了多態。

C++ 中普通成員函數加上 virtual 關鍵字就成爲虛函數。

Java 中其實沒有虛函數的概念,它的普通函數就至關於 C++ 的虛函數,動態綁定是 Java 的默認行爲。若是 Java 中不但願某個函數具備虛函數特性,能夠加上 final 關鍵字變成非虛函數。

PS: 其實 C++ 和 Java 在虛函數的觀點大同小異,殊途同歸罷了。

2. Java抽象函數(純虛函數)

抽象函數或者說是純虛函數的存在是爲了定義接口。

C++ 中純虛函數形式爲:

virtual void print() = 0;

Java 中純虛函數形式爲:

abstract void print();

PS: 在抽象函數方面 C++ 和 Java 仍是換湯不換藥。

3. Java 抽象類

抽象類的存在是由於父類中既包括子類共性函數的具體定義,也包括須要子類各自實現的函數接口。抽象類中能夠有數據成員和非抽象方法。

C++ 中抽象類只須要包括純虛函數,既是一個抽象類。若是僅僅包括虛函數,不能定義爲抽象類,由於類中其實沒有抽象的概念。

Java 抽象類是用 abstract 修飾聲明的類。

PS: 抽象類實際上是一個半虛半實的東西,能夠所有爲虛,這時候變成接口。

4. Java 接口

接口的存在是爲了造成一種規約。接口中不能有普通成員變量,也不能具備非純虛函數。

C++ 中接口其實就是全虛基類。

Java 中接口是用 interface 修飾的類。

PS: 接口就是虛到極點的抽象類。

5. 小結

C++ 虛函數    ==  Java 普通函數

C++ 純虛函數  ==  Java 抽象函數

C++ 抽象類    ==  Java 抽象類

C++ 虛基類    ==  Java 接口
相關文章
相關標籤/搜索