允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
1)一个对象的实际类型是确定的
例如: new Student(); new Person();等
2)可以指向对象的引用的类型有很多
例如: Student继承了Person类
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
因为Person和Object都是Student的父类型
注:一个对象的实际类型是确定,但是可以指向这个对象的引用的类型,却是可以是这对象实际类型的任意父类型。
3)一个父类引用可以指向它的任何一个子类对象
例如:
Object o = new AnyClass();
Person p = null;
p = new Student();
p = new Teacher();
p = new Person();
4)多态中的方法调用
例如:
public class Person{
public void run(){}
}
public class Student extends Person{
}
//调用到的run方法,是Student从Person继承过来的run方法
main:
Person p = new Student();
p.run();
例如:
public class Person{
public void run(){}
}
public class Student extends Person{
public void run(){
//重写run方法
}
}
//调用到的run方法,是Student中重写的run方法
main:
Person p = new Student();
p.run();
注:子类继承父类,调用a方法,如果a方法在子类中没有重写,那么就是调用的是子类继承父类的a方法,如果重写了,那么调用的就是重写之后的方法。
5)子类中独有方法的调用
例如:
public class Person{
public void run(){}
}
public class Student extends Person{
public void test(){
}
}
main:
Person p = new Student();
//调用到继承的run方法
p.run();
//编译报错,因为编译器检查变量p的类型是Person,但是在Person类中并没有发现test方法,所以编译报错.
p.test();
注:一个变量x,调用一个方法test,编译器是否能让其编译通过,主要是看声明变量x的类型中有没有定义test方法,如果有则编译通过,如果没有则编译报错.而不是看x所指向的对象中有没有test方法.
思考:为什么编译器会是这样检查?
6)子类引用和父类引用指向对象的区别
Student s = new Student();
Person p = new Student();
变量s能调用的方法是Student中有的方法(包括继承过来的),变量p能调用的方法是Person中有的方法(包括继承过来的)。
但是变量p是父类型的,p不仅可以指向Student对象,还可以指向Teacher类型对象等,但是变量s只能指向Studnet类型对象,及Student子类型对象。变量p能指向对象的范围是比变量s大的。
Object类型的变量o,能指向所有对象,它的范围最大,但是使用变量o能调用到的方法也是最少的,只能调用到Object中的声明的方法,因为变量o声明的类型就是Object.
7)多态的使用
如果使用多态解决以下问题:
public class Game{
public void start(BasketBall ball){
ball.run();
}
}
public class BasketBall{
public void run(){
//执行篮球游戏程序
}
}
在这种情况下,用户不断的变动需求:
想要增加足球游戏的运行
想要增加乒乓球游戏的运行
想要增加橄榄球游戏的运行
想要增加羽毛球球游戏的运行
想要增加铅球游戏的运行
....
如何处理?