• Java多态


    多态概述

    多态是面向对象三大特征之一,是同一个对象,在不同时刻表现出来的不同形态的能力。

    二哈

    举个例子:二哈;
    我们可以说二哈是狗:Dog erha = new Dog();
    我们也可以说二哈是动物:Animal erha = new Animal();
    同样这只二哈,在不同的时刻表现出来了不同的形态,这就是多态。

    多态的三个必要条件:

    • 继承
    • 子类重写父类方法
    • 有父类引用指向子类对象

    怎么理解这三个条件呢,直接上代码:

    // 动物类
    class Animal {
        public void eat() {
            System.out.println("动物吃东西");
        }
    }
    
    // 狗狗类(继承了动物类)
    class Dog extends Animal {
        // 重写父类eat()方法
        @Override
        public void eat() {
            System.out.println("狗狗吃骨头");
        }
    }
    
    // Demo类
    public class PolymorphismDemo {
        public static void main(String[] args) {
            // 父类引用指向子类对象
            Animal erha = new Dog();
            erha.eat();
        }
    }
    

    最后的运行结果是狗狗吃骨头,三个条件我在注释中也都标注了出来。这就是最基本的一个多态案例。

    多态中成员访问特点

    • 成员变量:编译看左边,执行看左边
    Animal erha = new Dog();
    System.out.println(erha.name); // erha.name只能取到父类Animal中的值
    
    • 成员方法:编译看左边,执行看右边
    Animal erha = new Dog();
    erha.eat(); // erha.eat()调用的是子类Dog重写后的方法
    

    怎么理解这两句话呢,直接上代码:

    // 动物类
    class Animal {
        public String name = "动物";
    
        public void eat() {
            System.out.println("动物吃东西");
        }
    }
    
    // 狗狗类
    class Dog extends Animal {
        public String name = "狗狗";
    
        @Override
        public void eat() {
            System.out.println("狗狗吃骨头");
        }
    }
    
    // Demo类
    public class PolymorphismDemo2 {
        public static void main(String[] args) {
            Animal erha = new Dog();
            System.out.println(erha.name);
            erha.eat();
        }
    }
    

    最后的运行结果是:

    动物
    狗狗吃骨头
    

    为什么成员变量和成员方法的访问不一样呢?
    因为成员方法有重写,eat()被子类重写了;而成员变量没有重写,访问的依然是父类的name

    多态的弊端

    不能使用子类的特有功能,举个例子

    // 动物类
    class Animal {
        public String name = "动物";
    
        public void eat() {
            System.out.println("动物吃东西");
        }
    }
    
    // 狗狗类
    class Dog extends Animal {
        public String name = "狗狗";
        public int age = 5;
    
        @Override
        public void eat() {
            System.out.println("狗狗吃骨头");
        }
    
        public void bark(){
            System.out.println("狗狗汪汪叫");
        }
    }
    
    // Demo类
    public class PolymorphismDemo3 {
        public static void main(String[] args) {
            Animal erha = new Dog();
            System.out.println(erha.name);
            erha.eat();
    
            //System.out.println(erha.age); //ERROR
            //erha.bark(); //ERROR
        }
    }
    

    因为这个erha是父类引用(Animal)指向子类对象(Dog)所创建出来的,子类的特有功能agebark()这边都没法获取,所以这边两行都会报错。

    多态中的转型

    • 向上转型:父类引用指向子类对象
    • 向下转型:父类引用转为子类对象
    Animal a = new Dog(); // 向上转型,父类引用指向子类对象
    Dog d = (Dog) a; // 向下转型,父类引用被强制转换为子类对象
    

    在代码中实现:

    // 动物类
    class Animal {
        public void eat() {
            System.out.println("动物吃东西");
        }
    }
    
    // 狗狗类
    class Dog extends Animal {
        @Override
        public void eat() {
            System.out.println("狗狗吃骨头");
        }
    
        public void bark(){
            System.out.println("狗狗汪汪叫");
        }
    }
    
    // Demo类
    public class PolymorphismDemo4 {
        public static void main(String[] args) {
            Animal erha = new Dog(); // 向上转型
            erha.eat();
            //erha.bark(); //ERROR
    
            Dog xiaoha = (Dog) erha; // 向下转型
            xiaoha.eat();
            xiaoha.bark();
        }
    }
    

    最后的运行结果是:

    狗狗吃骨头
    狗狗吃骨头
    狗狗汪汪叫
    

    在向上转型中,由于是父类引用指向子类对象,因此无法调用bark()方法,而在向下转型中,父类引用转为子类对象,因此可以调用子类的bark()方法。

  • 相关阅读:
    sqlserver临时表或表变量代替游标
    Server嵌套事务处理的方法
    数据库一对一,一对多,多对多关系
    VS NuGet离线包(缓存包)nupkg安装
    搭建属于自己的NuGet服务器
    SQL Server Management Studio(SSMS)的使用与配置整理
    原来以为京东售后很好,现在才知道 京东售后就是个垃圾!
    [asp.net]C#实现json的序列化和反序列化
    ASP.NET中JSON的序列化和反序列化
    Javascript中判断变量是数组还是对象(array还是object)
  • 原文地址:https://www.cnblogs.com/Subaru/p/15741404.html
Copyright © 2020-2023  润新知