• Java中的多态


    什么是多态?

    多态,书面解释是“同一个行为具有不同表现形式或形态的能力”,我的理解是,如果一个对象可以衍生出多种形态,那么这就叫多态。对象就相当于模板。举个例子,比如制衣厂里进行生产的图纸。制衣图纸就有很多不同的表达或实现,比如有粉色衣服、黑色衣服、白色衣服、大小号衣服等等。当制衣厂根据图纸做出五颜六色尺码不同的衣服后,我们就可以说"制衣图纸"这个对象具备多态性。多态的本质就是允许将子类对象的地址调用到父类栈上的引用变量

    多态的前提

    1. 子类继承父类,比如 class Zi extends Fu{ }
    2. 子类重写父类方法,重写就是将父类中的方法照抄一遍,可以更改方法体。
    3. 父类引用指向子类对象,比如 Fu fu = new Zi();,左边的Fu fu 是父类引用,左边的new Zi();是子类对象。

    多态的分类

    • 重载式多态,也叫编译时多态。也就是说,这种多态再编译时已经确定好了。重载大家都知道,方法名相同而参数列表不同 的一组方法就是重载。在调用这种重载的方法时,通过传入不同的参数最后得到不同的结果。
    • 重写式多态,也叫运行时多态。这种多态通过动态绑定技术来实现,是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。也就是说,只有程序运行起来,你才知道调用的是哪个类的方法。我们接下来讲的所有多态都是重写式多态,因为它才是面向对象编程中真正的多态。

    多态的优缺点

    1. java 多态的好处:
      A:提高了代码的维护性(继承保证)
      B:提高了代码的扩展性(由多态保证)
    2. 多态的弊端
      A:向上转型不能使用子类的特有功能。
      B:解决方案是向下转型

    多态成员访问的特点

    Fu fu = new Zi();时,即左边是父类,右边是子类。

    • 变量一律为:编译左边,运行左边

    方法则需要分为两种情况

    • 静态成员方法: 编译左边,运行左边
    • 非静态成员方法:编译左边,运行右边

    “编译和运行”的理解:比如编译看左边/右边,指的是去类中找指定的变量或者方法,编译在左就去左边找,编译在右就去右边找,能找到就编译正常,找不到代码就会报错。运行看左边/右边则指的是,如果子父类中有同名变量或者方法时,会优先调用谁。运行在左就调用父类,运行在右就调用子类。

    规律:
    1. 编译都看的是左边
    2. 变量一律是编译左边,运行左边
    3. 只有非静态是编译左边,运行右边

    多态中的向上转型和向下转型

    • 向上转型:子类转为父类,自动转型。格式Fu fu = new Zi();,向上转型就像说狗是动物,连衣裙是衣服,我是人一样。以花木兰代父从军为例,花木兰冒充父亲就必须舍弃自己的姓名,以老爹的名字在军营过男儿的生活。即向上转型后,父类的引用fu所指向的属性是父类的属性。但是上阵杀敌的人的确是花木兰,即如果子类重写了父类的方法(如上阵杀敌),那么父类引用fu指向的或者调用的方法就是子类的方法,这个叫动态绑定。花木兰从军后必须摒弃女儿家的习惯,如娇羞和女红。即向上转型后,父类引用不能调用子类自己的方法(就是父类没有子类才有的方法)

    总结:向上转型会丢失子类的新增方法,同时会保留子类重写的方法

    • 向下转型:父类转为子类,需要强制转换。向下转型后就可以使用子类特有的功能了。就如同战争结束后,木兰又恢复了女儿身,可以娇羞,做女红,嫁人了。向下转型,既可以调用父类,也可以调用子类,但优先调用子类。
    向下转型格式
    Fu fu = new Zi();
    Zi zi = (Zi) fu;
    

    示例代码

    动物类(父类)
    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 = 80;
        static int age = 90;
        String name = "tomCat";
        public void eat() {
            System.out.println("猫吃饭");
        }
        public static void sleep() {
            System.out.println("猫在睡觉");
        }
        public void catchMouse() {
            System.out.println("猫在抓老鼠");
        }
    
    }
    
    测试类
    class Demo_Test {
        public static void main(String[] args) {
    
            Animal am = new Cat();//向上转型
            am.eat();//eat()是非静态成员方法,编译先看左边父类,但执行的是右边子类(右边)
            am.sleep();//sleep()是静态成员方法,编译看左边父类,优先执行父类(左边)
            am.run();//run()是父类方法,优先执行父类。(左)
            // am.catchMouse(); 报错,catchMouse是子类非静态方法,编译是看左边父类的。父类没有,所以报错
            //System.out.println(am.name); 报错,name是右边子类的非静态成员变量,编译看左边,左边没有name,所以报错
            System.out.println(am.num);//num是非静态成员变量,编译看左边父类,运行看左边
            System.out.println(am.age);//age是静态成员变量,编译看左边,运行看左边。
    
            /*
            * 总结:
            * 当Fu fu = new Zi()时,即左边是父类,右边是子类
            *   变量一律为:编译左边,运行左边
            *   方法需要分为两种情况
            *       静态成员方法: 编译左边,运行左边
            *       非静态成员方法:编译左边,运行右边
            *
            * 规律:
            * 1.编译都看的是左边
            * 2.变量一律是编译左边,运行左边
            * 3.只有非静态是编译左边,运行右边
            * */
            System.out.println("------------------------------");
    
            Cat ct = (Cat)am;//向下转型,既可以调用父类,也可以调用子类,但优先调用子类。
            ct.eat();
            ct.sleep();
            ct.run();
            ct.catchMouse();
            System.out.println(ct.name);
            System.out.println(ct.age);
        }
    }
    
    
    运行结果
    猫吃饭
    动物在睡觉
    动物在奔跑
    10
    20
    ------------------------------
    猫吃饭
    猫在睡觉
    动物在奔跑
    猫在抓老鼠
    tomCat
    90
    
    参考链接:JAVA的多态用几句话能直观的解释一下吗?
  • 相关阅读:
    快速提交一个项目到github或gitee上
    微信web开发问题记录
    解决 VUE项目过大nodejs内存溢出问题
    vue使用动态渲染v-model输入框无法输入内容
    webstorm 支持vue element-ui 语法高亮属性自动补全
    spring websocket报错:No matching message handler methods.
    Failed to start bean 'stompBrokerRelayMessageHandler'; nested exception is java.lang.NoClassDefFoundError: reactor/io/codec/Codec
    远程调用appium server
    appium 特殊操作
    mac下搭建appium
  • 原文地址:https://www.cnblogs.com/anycall/p/10730710.html
Copyright © 2020-2023  润新知