[TOC]
上节课的总结:
继承
异常:
上节课我们讲到了Java类的继承,子类可以继承父类。
那么,可以将子类看作特殊的父类
Java种可以将子类对象直接赋值给父类的一个变量,系统会自动完成类型转换,称之为上转型。
//这里Student时Person的子类
Person p = new Student();
了解了这个概念之后,接下来我们要讲解多态。
多态是面向对象编程的三大特征之一。
多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时实际类型的方法,例如:
public void runTwice(Person p) {
p.run();
p.run();
}
它传入的参数类型是Person,但是子类是特殊的父类
我们无法知道传入的参数实际类型究竟是还是Student,还是Person的其他子类,因此,也无法确定调用的是不是Person类定义的run()方法。
运行期才能动态决定调用的子类方法就是多态的特性。
这种不确定性的方法调用,究竟有什么作用呢?
举一个例子:
每个公民都是纳税人,我们需要写一个程序统计纳税人应该纳多少税。
假设我们定义一种普通收入,需要给它报税,那么先定义一个Income类:
(这个类是所有收入的父类,也成为基类)
class Income {
public double income;
public double getTax() {
return income * 0.1;
}
}
对于工资收入,咱们国家是要求工资低于个税起征点的部分不用交个人所得税,目前这个数是5000。工资高于5000的,可以减去5000再收税。讲义中忽略了专项扣除和预扣预缴税额,假设税率为20%。
那么我们可以从Income
派生出SalaryIncome
,并覆盖getTax()
方法。
(继承和派生是不同的说法)
class Salary extends Income {
@override
public double getTax() {
if(income <= 5000) {
return 0;
}
return (income - 5000) * 0.2;
}
}
假如你是高层次技术人员和高技能人才,那么你可能享受国务院特殊津贴,发给你的奖金你就不需要交税了
class SpecialAllowance extends {
@Override
public double getTax() {
return 0;
}
}
现在,我们要编写一个报税的财务软件,对于一个人的所有收入进行报税,可以这么写:
注意,这里参数的写法Type...
,表示可以传入的参数个数不确定。
public double totalTax(Income... incomes) {
double total = 0;
for(Income income : income) {
total = total + income.getTax();
}
}
然后整合下来的程序就是这样:
public class Solution {
public static void main(String args[]) {
//给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
Income[] incomes = new Income[] {
new Income(300),
new Salary(7500),
new SpecialAllowance(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 SpecialAllowance extends Income {
public SpecialAllowance(double income) {
super(income);
}
@Override
public double getTax() {
return 0;
}
}
观察totalTax()方法:利用多态,totalTax()方法只需要和Income打交道,它完全不需要知道Salary和SpecialAllowance的存在,就可以正确计算出总的税收
如果我们要新增一种稿费收入,只需要从Income派生,然后正确覆写getTax()方法就可以。把新的类型传入totalTax(),不需要修改任何代码
多态具有一个非常强大的功能,就是允许添加更多类型的子类实现功能拓展,却不需要修改基于父类的代码