• 面向对象的三大特性之三——多态



    typora-copy-images-to: images

    什么是多态?

    举例:

    一般对象这样创建:

    猫 x = new 猫();建立了猫的对象,并通过本类引用x指向了这个猫对象;

    多态中的对象:

    动物 x1 = new 猫();父类引用x1指向了子类这个猫对象;

    x1这个引用即具备猫的形态,又具备着动物的形态。

    简单的说:就是一个对象对应着不同类型,在代码中如何体现呢?父类或者接口的引用指向其子类的对象。

    多态存在的三个前提:

    1. 要有继承关系
    2. 子类重写父类方法
    3. 父类引用指向子类对象

    多态举例

    父类Animal

    class Animal {
        int num = 10;
        static int age = 20;
    
        public void eat() {
            System.out.println("动物吃饭");
        }
        public static void sleep(){
            System.out.println("动物睡觉");
        }
        public void run(){
            System.out.println("动物在奔跑");
        }
    }
    

    子类Cat

    class Cat extends Animal{
        int num  = 66;
        static int age = 40;
        String name = "tomCat";
    
        public void eat() {
            System.out.println("猫吃饭");
        }
    
        public static void sleep(){
            System.out.println("猫睡觉");
        }
    
        public void catMouse(){
            System.out.println("猫在抓老鼠");
        }
    }
    

    测试类

    /**
     * @ClassName: DuotaiDemo
     * @author: benjamin
     * @version: 1.0
     * @description: 多态举例
     */
    public class DuotaiDemo {
        public static void main(String[] args) {
    
            // 父类引用指向了子类对象
            Animal am = new Cat();
    
            am.eat();
            am.sleep();
            am.run();
    
            System.out.println(am.num);
            System.out.println(am.age);
        }
    }
    

    结果

    猫吃饭
    动物睡觉
    动物在奔跑
    10
    20

    发现问题

    子类重写了非静态成员方法eat(): 猫吃饭

    子类重写了静态成员方法sleep(): 动物睡觉

    子类未重写父类成员方法run():动物在奔跑

    总结:

    成员变量:编译看左边(父类),运行看左边(父类)

    成员方法:编译看左边(父类),运行看右边(子类)

    静态方法:不涉及对象的多态性。因为静态函数随着类的加载而加载。直接用类名调用即可。

    特点举例

    成员变量

    简单地说:编译和运行都参考等号的左边

    编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,没有,编译失败;

    运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。

    举例:

    执行DuotaiFu f = new DuotaiZi(); 此时子类型提升为父类型,用父类型找父

    public class DuotaiDemo2 {
        public static void main(String[] args) {
    
            DuotaiFu f = new DuotaiZi();
    
            System.out.println(f.num);//3
    
        }
    
    }
    class DuotaiFu{
        int num = 3;
    }
    
    class DuotaiZi extends DuotaiFu{
        int num = 4;
    }
    

    内存图解

    成员函数(重点)

    非静态函数

    简单说:编译时看左边,运行时看右边

    编译时:参考引用变量所属的类中是否有调用的函数,有,编译通过,没有,编译失败;

    运行时:参考的是对象所属的类中是否有调用的函数。

    举例:

    show函数运行时,持有this引用,指向了0x0034的对象(new Zi() ),找到该对象的show方法运行;

    public class DuotaiDemo2 {
        public static void main(String[] args) {
    
            DuotaiFu f = new DuotaiZi();
            f.show();
        }
    }
    class DuotaiFu{
    
         void show(){
             System.out.println("fu show...");
         }
    }
    
    class DuotaiZi extends DuotaiFu{
        void show(){
            System.out.println("zi show...");
        }
    }
    // zi show...
    

    内存图解:

    静态函数

    不涉及对象的多态性。因为静态函数随着类的加载而加载。直接用类名调用即可。

    编译时:参考引用型变量所属的类中是否有调用的静态方法;

    运行时:参考引用型变量所属的类中是否有调用的静态方法;

    举例:

    非静态方法必须绑定到指定的对象上,才能运行;

    package java_demo_2;
    
    public class DuotaiDemo2 {
        public static void main(String[] args) {
    
            DuotaiFu f = new DuotaiZi();
            f.method();
            DuotaiFu.method();
            DuotaiZi.method();
    
        }
    
    }
    class DuotaiFu{
    
         void show(){
             System.out.println("fu show...");
         }
    
         static void method(){
             System.out.println("父类静态方法");
         }
    }
    
    class DuotaiZi extends DuotaiFu{
        void show(){
            System.out.println("zi show...");
        }
        static void method(){
            System.out.println("子类静态方法");
        }
    }
    

    结果:

    父类静态方法
    父类静态方法
    子类静态方法

    向上转型和向下转型

    向上转型:

    • 概念:Animal a = new Cat(); 猫提升成动物类型,但是猫特有的功能无法访问。
    • 目的:限制对特有功能的访问,专业讲就是向上转型。

    向下转型:

    • 概念:如果还想用具体动物猫的特有功能,可以将对象进行向下转型。如:

      Cat c = (Cat) am;

      c.catchMouse();

    • 目的:为了使用子类中的特有方法。

    举例:

    // 向上转型
    Animal am = new Cat();
    am.eat();
    
    // 向下转型
    Cat cat = (Cat) am;
    cat.catMouse();
    System.out.println(cat.name);
    
    输出
    猫在抓老鼠
    tomCat
    

    类型转换异常:

    对于转型,自始至终都是在类对象在做着类型的变化。猫-动物-猫

    Cat c2 = (Cat) d;
    c2.catchMouse();//ClassCastException
    // 不能把一个猫——动物——狗;报错
    

    类型判断:

    instanceof :运行时指出对象是否是特定类的一个实例,只能用于引用数据类型判断,通常在向下转型前用于健壮性的判断。

    举例:

    public class DuotaiDemo {
        public static void main(String[] args) {
            //向上转型
            Animal c = new Cat();
            Animal d = new Dog();
    
            method(c);
            method(d);
    
        public static void method(Animal a){ 
    
            a.eat();
            if(a instanceof Cat){
    
                Cat c = (Cat) a;//向下转型,执行对象的特有方法;
                c.catchMouse();
            }
            else if(a instanceof Dog){
                Dog d = (Dog) a;
                d.lookHome();
            }
        }
    }
    

    参考链接

    JAVA的多态用几句话能直观的解释一下吗? - 程序狗的回答 - 知乎
    https://www.zhihu.com/question/30082151/answer/120520568

  • 相关阅读:
    了解自我
    IT技能栈
    客户端的工作不仅仅只是看起来那么简单
    .NET 基础 一步步 一幕幕[XML基础操作]
    .NET 基础 一步步 一幕幕[Winform应用程序]
    .NET 基础 一步步 一幕幕[面向对象之堆、栈、引用类型、值类型]
    .NET 基础 一步步 一幕幕[面向对象之new、this关键字]
    .NET 基础 一步步 一幕幕[面向对象之静态、非静态]
    .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
    .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]
  • 原文地址:https://www.cnblogs.com/benjieqiang/p/11481801.html
Copyright © 2020-2023  润新知