多态概述 

现实事物经常会体现出多种形态,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());
}

小结

多态:基类型对象访问派生类重写的方法

循环调用基类对象,访问不同派生类方法

实参是派生类;行参是基类