Java多态

    |     2015年3月30日   |   Java面向对象   |     0 条评论   |    1866

面向对象三大特性:封装、继承、多态。封装藏起内部实现,改结构不影响外部用法,也保护数据——外界只看见访问方法。继承为了复用父类代码,同时也给多态铺路。

多态说的是:同一份引用、同一次方法调用,实际跑哪段代码,取决于对象真正的类型。

一、现实生活中的多态

同一个 F1 键:在浏览器窗口打开新网页,在 Word 打开帮助中心,在 Windows 桌面弹出「帮助和支持」。按键行为一样,表现形态不同,这就是生活里的多态。

二、软件世界中的多态

class People {
    void say() {
        System.out.println("大家好,我是良民");
    }
}
class Teacher extends People {
    void say() {
        System.out.println("大家好,我是一名老师");
    }
}
public class Demo {
    public static void main(String[] args) {
        People obj = new People(); // 引用父类实例
        obj.say();
        obj = new Teacher(); // 引用子类实例
        obj.say();
    }
}
// 运行结果:
// 大家好,我是良民
// 大家好,我是一名老师

obj 的声明类型是 People,既可以指向 People 实例,也可以指向 Teacher 实例。它有时是「人类」,有时是「教师」,形态不同,就是多态。再比如去宠物店说「请给我一只宠物」,小猫、小狗、蜥蜴都算数——「宠物」具备多态性。

反过来不行:所有教师都是人,不是所有人都是教师。

public static void main(String[] args) {
    Teacher obj = new Teacher();
    obj.say();
    obj = new People(); // 编译错误:不能把父类实例赋给子类变量
    obj.say();
}

结论:父类变量可以引用父类实例,也可以引用子类实例;反过来错误。

三、多态的三个条件

条件 含义
继承 必须有父子类关系
重写(覆盖) 子类重新定义父类方法,调用时才可能走到子类版本
父类变量引用子类对象 编译期按父类看方法,运行期按实际对象绑定

用多态方式调用方法时:先看父类有没有这个方法——没有则编译错误;有则再看子类有没有覆盖。覆盖了就调子类,否则调父类。

  • 用父类类型的引用指向子类对象;
  • 该引用在编译期只能调用父类中定义的方法和变量;
  • 若子类重写了父类方法,运行时调用的是子类那一份。

一句话总结:父类引用指向子类对象,编译看父类有没有方法,运行走子类覆盖后的实现。

转载请注明来源:Java多态
本文链接地址:https://ai.zhousir.top/?p=85
回复 取消