多态: Java的实例方法调用是基于运行时的实际类型的动态调用, 而非变量的声明类型. 具体的应用在下面会讲到.
在继承关系中, 子类如果定义了一个与父类方法签名完全相同的方法, 被称为覆写(Override
).
例如:
class Person {
public void run() {
System.out.println("Person.run");
}
}
//在子类Student中,覆写这个run()方法:
class Student extends Person {
@Override
public void run() {
System.out.println("Student.run");
}
}
Override和Overload的不同之处在于:
-
Overload
: 方法签名不同 -
Override
: 方法签名相同, 并且返回值也相同.
具体的对比可以在下图中发现.
class Person {
public void run() { … }
}
class Student extends Person {
// 不是Override,因为参数不同:
public void run(String s) { … }
// 不是Override,因为返回值不同:
public int run() { … }
}
在下面的代码中, 子类student
覆写了父类Person
的方法, 那在这个引用类型为Person
, 实际类型为Student
的变量, 调用的方法是子类Student的run()
. 这种特性在面向对象中称之为多态(Polymorphic).
public class Main {
public static void main(String[] args) {
Person p = new Student();
p.run(); // 应该打印Person.run还是Student.run?
}
}
class Person {
public void run() {
System.out.println("Person.run");
}
}
class Student extends Person {
@Override
public void run() {
System.out.println("Student.run");
}
}
多态是指, 针对某个类型的方法调用, 其真正执行的方法取决于运行时期实际类型的方法.
在子类的覆写方法中, 如果要调用父类的覆写方法, 可以通过super
来调用. 例如:
class Person {
protected String name;
public String hello() {
return "Hello, " + name;
}
}
Student extends Person {
@Override
public String hello() {
// 调用父类的hello()方法:
return super.hello() + "!";
}
}
因为继承可以覆写父类的方法, 但如果一个父类 不允许子类对其某个方法进行覆写的话, 可以用final
将其标记, 而一旦被final
修饰, 则该方法不能再被修改.
class Person{
protected String name;
public final String hello (){
return "Hello, " + name;
}
}
Student extends Person{
//compile error: 不允许覆写
@Override
public String Hello(){
...
}
}
final
同样可以修饰类, 或者实例字段. 当实例字段被修饰后, 可以在构造方法中进行初始化:
class Person{
public final String name;
public Person(String name){
this.name = name;
}
}
全文实例:
给一个有工资收入和稿费收入的小伙伴算税:
public class Main {
public static void main(String[] args) {
Income[] incomes = new Income[] { new Income(3000), new SalaryIncome(7500), new RoyaltyIncome(12000) };
double total = 0;
for (Income income: incomes) {
total = total + income.getTax();
}
System.out.println(total);
}
}
public class Income {
protected double income;
public Income(double income) {
this.income = income;
}
public double getTax() {
return income * 0.1; // 税率10%
}
}
public class SalaryIncome extends Income {
public SalaryIncome(double income) {
super(income);
}
@Override
public double getTax() {
if (income <= 5000) {
return 0;
}
return (income - 5000) * 0.2;
}
}
/**
* 稿费收入税率是20%
*/
public class RoyaltyIncome extends Income {
public RoyaltyIncome(double income) {
super(income);
}
@Override
public double getTax() {
return income *0.2;
}
}