Java 面向對象-多態 ②

假設我們編寫這樣一個方法:

public void runTwice(Person p) {
    p.run();
    p.run();
}

它傳入的參數類型是Person,我們是無法知道傳入的參數實際類型究竟是Person,還是Student,還是Person的其他子類,因此,也無法確定調用的是不是Person類定義的run()方法。

所以,多態的特性就是,運行期才能動態決定調用的子類方法。對某個類型調用某個方法,執行的實際方法可能是某個子類的覆寫方法。這種不確定性的方法調用,究竟有什麼作用?

我們還是來舉栗子。

假設我們定義一種收入,需要給它報稅,那麼先定義一個Income類:

class Income {
    protected double income;
    public double getTax() {
        return income * 0.1; // 稅率10%
    }
}

對於工資收入,可以減去一個基數,那麼我們可以從Income派生出SalaryIncome,並覆寫getTax()

class Salary extends Income {
    @Override
    public double getTax() {
        if (income <= 5000) {
            return 0;
        }
        return (income - 5000) * 0.2;
    }
}

如果你享受國務院特殊津貼,那麼按照規定,可以全部免稅:

class StateCouncilSpecialAllowance extends Income {
    @Override
    public double getTax() {
        return 0;
    }
}

現在,我們要編寫一個報稅的財務軟件,對於一個人的所有收入進行報稅,可以這麼寫:

public double totalTax(Income... incomes) {
    double total = 0;
    for (Income income: incomes) {
        total = total + income.getTax();
    }
    return total;
}

來試一下:

public class Main {
    public static void main(String[] args) {
        // 給一個有普通收入、工資收入和享受國務院特殊津貼的小夥伴算稅:
        Income[] incomes = new Income[] {
            new Income(3000),
            new Salary(7500),
            new StateCouncilSpecialAllowance(15000)
        };
        System.out.println(totalTax(incomes));
    }

    public static double totalTax(Income... incomes) {
        double total = 0;
        for (Income income: incomes) {
            total = total + income.getTax();
        }
        return total;
    }
}

class Income {
    protected double income;

    public Income(double income) {
        this.income = income;
    }

    public double getTax() {
        return income * 0.1; // 稅率10%
    }
}

class Salary extends Income {
    public Salary(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        if (income <= 5000) {
            return 0;
        }
        return (income - 5000) * 0.2;
    }
}

class StateCouncilSpecialAllowance extends Income {
    public StateCouncilSpecialAllowance(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        return 0;
    }
}

觀察totalTax()方法:利用多態,totalTax()方法只需要和Income打交道,它完全不需要知道SalaryStateCouncilSpecialAllowance的存在,就可以正確計算出總的稅。

如果我們要新增一種稿費收入,只需要從Income派生,然後正確覆寫getTax()方法就可以。把新的類型傳入totalTax(),不需要修改任何代碼。

可見,多態具有一個非常強大的功能,就是允許添加更多類型的子類實現功能擴展,卻不需要修改基於父類的代碼。

Java 面向對象-多態 ①

Java 面向對象-多態 ②

Java 面向對象-多態 ③

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章