多态概述
现实事物经常会体现出多种形态,Java作为面向对象的语言,可以描述一个事物的多种形态,如Student类继承了Person类,一个Student的对象张三便既是Student,又是Person。
多态分为两种:
a.编译时多态:方法的重载,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
b. 运行时多态:Java运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。
多态存在的必要条件:
1.要有继承关系
2.要有方法覆盖
3.父类引用指向了子类的实例
多态中成员的特点:
“成员变量,静态方法看左边;非静态方法:编译看左边,运行看右边。”
向上转型和向下转型
1.对象的向上转型:
格式:父类名称 对象名 = new 子类名称();
含义:右侧创建了一个子类对象,把它当作父类来使用。
GradedActivity 类是 FinalExam 类的基类。
我们可以用exam变量存放一个 FinalExam 对象的地址。
GradedActivity exam = new FinalExam(50, 7);
->
FinalExam finalExam = new FinalExam(50, 7);
GradedActivity exam = finalExam; //向上转型
注意:
向上转型不要强制转型。
父类引用指向的或者调用的方法是子类的方法,这个叫动态绑定。
向上转型后父类引用不能调用子类自己的方法。
2.对象的向下转型:
格式:子类名称 对象名 =(子类名称) 父类对象;
含义:将子类还原,还原成为本来的子类对象
public class Human {
public void sleep() {
System.out.println("Human sleep..");
}
public static void main(String[] args) {
// (1)向上转型
Male m1 = new Male();
Human h1 = m1;
h1.sleep();
//h1.speak(); // 此时需要向下转型,否则不能调用speak方法。
// // (2)向下转型
// Male m2 = new Male();
// Human h2 = m2;
// m2 = (Male) h2;
// m2.speak();
// // (3)向下转型:失败
// Human h3 = new Human();
// Male m3 = (Male)h3;
// m3.speak(); //此时会出现运行时错误,所以可以用instanceOF判断
//
// // (4)向下转型:类型防护
// Human h4 = new Human();
// if (h4 instanceof Male){ // 因为h4不是Male的实例,所以不执行if内部代码
// Male m4 = (Male)h4;
// m4.speak();
// }
}
}
class Male extends Human {
@Override
public void sleep() {
System.out.println("Male sleep..");
}
public void speak() {
System.out.println("I am Male");
}
}
instanceof关键字
java 中的instanceof运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
用法: result = object instanceof class
如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。
Fu f1=new Zi();
Fu f2=new Son();
if(f1 instanceof Zi){
System.out.println("f1是Zi的类型");
}
else{
System.out.println("f1是Son的类型");
}
多态示例
GradedActivity[] tests = new GradedActivity[3];
// 第一次考试采用五级计分制,考了75
tests[0] = new GradedActivity();
tests[0].setScore(75);
// 第二次考试采用二级计分制(P或者F)。总共20题,每题分值相同,考生答错5题。
// 通过的最低分数线是60分
tests[1] = new PassFailExam(20, 5, 60);
// 第三次是期末考试也采用五级计分制. 总共50题,每题分值相同,考试答错7题
tests[2] = new FinalExam(50, 7);
// 显示每次考试的分数和等级
for(int i=0; i<tests.length; i++){
System.out.println("Score: " + tests[i].getScore()+ "\t" +
"Grade: " + tests[i].getGrade());
}
public static void main(String[] args) {
GradedActivity[] tests = new GradedActivity[3];
// 第一次考试采用五级计分制,考了75
tests[0] = new GradedActivity();
tests[0].setScore(75);
// 第二次考试采用二级计分制(P或者F)。总共20题,每题分值相同,考生答错5题。
// 通过的最低分数线是60分
tests[1] = new PassFailExam(20, 5, 60);
// 第三次是期末考试也采用五级计分制. 总共50题,每题分值相同,考试答错7题
tests[2] = new FinalExam(50, 7);
// 显示每次考试的分数和等级
for(int i=0; i<tests.length; i++){
showValue(tests[i]);
}
}
public static void showValue(GradedActivity exam){
System.out.println("Score: " + exam.getScore()+ "\t" +
"Grade: " + exam.getGrade());
}
小结
多态:基类型对象访问派生类重写的方法
循环调用基类对象,访问不同派生类方法
实参是派生类;行参是基类