zoukankan      html  css  js  c++  java
  • 面向对象——多态与向上、向下转型机制

    前言

    开头先回忆一下,面向对象的三大特征:封装(数据抽象)、继承、多态。为什么多态排在最后一位,因为它是以前面两个为前提的,尤其是继承。

    多态概念梳理

    多态本质在于 同一种行为的多样化表达 (这句话不禁让我想起了基因的多样性表达,这是现实世界物种多态的原因)。

    对于某一种行为而言,它的多样性体现在两种可能:
    1. 行为主体相同,行为受体不同——同样是待客,为什么他对别人温柔对你凶?
    2. 行为受体相同,行为主体不同——同样是吃肉,人是煮熟吃,动物生吃。

    这是我们在生活中的例子,现在我们迁移到编程中的多态!

    我们是不是可以把一个方法称为一种行为,他的调用者我们称为“行为主体” ,他的参数我们称为”行为受体”呢,而把函数体看作是行为的具体内容?

    编程中,多态分为 编译时多态 和 运行时多态,也称为 前期绑定动态绑定

    注:存在说法认为多态仅仅限定于运行时的多态,本人认为还是以“同一种行为的多样化表达”的基准,说法是死的,思想是活的,大家也不用在这方面纠结。

    编译时多态:编程中的体现是方法重载,调用者是明确的,调用方法有多种,我们根据参数来确定调用哪个方法,从而体现多样性。
    运行时多态:根源于继承之后的方法重写,多个子类都继承了相同父类,并且都对父类中某个普通方法进行了重写,从而体现多样性。


    实验

    首先,先创建继承关系如下:
    image_1clkqo76a8jg14i41g8u17cfkj4d.png-12.3kB
    image_1clkqmn0m4q01mr8j91urq1cc230.png-11.5kB
    image_1clkqklrcrni1ov928h1ig2mqq2j.png-12.3kB

    转型

    能实现转型,是运行时多态的必要条件之一。
    编译的机制:
    根据你引用指定的类型去搜索你的方法是否存在,如果该引用类型中不存在调用方法,报错。
    运行时机制
    运行时,是根据引用所指的具体对象类型来调用方法。
    当我们将父类中的study()方法注释:
    image_1clkqhovg3n9oh41sihtsf6t1p.png-12.5kB
    运行时:
    image_1clkqjqgvkmn19uucks159mdce26.png-17.9kB
    从机器级角度分析这个问题:
    编译时根据对象引用确定该方法的符号引用名称,运行时根据对象引用指向的对象进行符号引用的重定位。

    向上转型

    如果你是一个大学生,那么你肯定也是一名学生。
    我们对你所属的范围进行了一次周延扩大,这就是一次向上转型。

    用处:
    1.提高了程序的扩充性,不需要写一些重复的代码。
    2.增加代码简洁性,可阅读性。

    假设我们有一个老师,他既教高中生,也教大学生,不同学生上课方式不同,正常那我们不是要进行方法重载为每个学生量身定制一个方法吗?但是我们可以让他们自适应:
    image_1clkqu5hefucqoh1e6rrce6eu5d.png-7.8kB
    image_1clkrf32l12p71ige1j2b1i1tdmo8h.png-20kB
    结果:
    image_1clkrffjc1oje1p5m13nctm2ele8u.png-10.7kB

    向上转型进阶分析:
    如果方法调用者和方法参数都是具有继承关系的类型,这个向上转型是怎么转的呢?
    观查测试样例:

    image_1cll2h6gt4ai51q14dg1fpfrlka8.png-25.3kB

    image_1cll2enkf14eg1ulvpktijhh9n9r.png-13.9kB

    输出:
        A and B
    

    当我们将A类中的show(B)注释掉:
    image_1cll2isddv8jiig1s68106ed9gal.png-24.1kB
    image_1cll2kq401lqu14di10dsjmtt56b9.png-13.5kB

    输出:
        B and A
    

    规律总结:

    先是调用者由下到上向上转型查找对应方法; 若没找到,每次将调用参数向上转型一次,再寻找对应方法。

    向下转型(注意点)

    你是一个学生,但不一定是大学生。向下转型,一定要注意类型的匹配。
    为什么又会有向下转型?向上转型的弊端在于被调用方法受到局限,而当你又想调用子类独有的方法,你就必须用 向下转型 转回去。
    所以向下转型一定是先有向上转型作铺垫的。
    但是,这边注意一点,你对象是什么类型,你转回去也应该是什么类型。

    人->动物->猪 ×
    人->动物->人 √
    image_1clkr5u6k18rvntl1im01vq11sh26q.png-26.7kB
    编译没有报错,但运行一定抛出转型异常。
    image_1clkramai1mmrr34rcs1nmpuui77.png-10kB
    正确做法:
    image_1clkrcdf327cvvg1og11j0d1g1h7k.png-13kB


    牛刀小试

    根据我们之前总结的规律,看看你的答案是否正确吧:

    class A {
        public String show(D obj) {
            return ("A and D");
        }
    
        public String show(A obj) {
            return ("A and A");
        }
    
    }
    
    class B extends A{
        public String show(B obj){
            return ("B and B");
        }
    
        public String show(A obj){
            return ("B and A");
        }
    }
    
    class C extends B{
    
    }
    
    class D extends B{
    
    }
    
    public class Demo {
        public static void main(String[] args) {
            A a1 = new A();
            A a2 = new B();
            B b = new B();
            C c = new C();
            D d = new D();
    
            System.out.println("1--" + a1.show(b));
            System.out.println("2--" + a1.show(c));
            System.out.println("3--" + a1.show(d));
            System.out.println("4--" + a2.show(b));
            System.out.println("5--" + a2.show(c));
            System.out.println("6--" + a2.show(d));
            System.out.println("7--" + b.show(b));
            System.out.println("8--" + b.show(c));
            System.out.println("9--" + b.show(d));
        }
    }
    
    输出:
        1--A and A
        2--A and A
        3--A and D
        4--B and A
        5--B and A
        6--A and D
        7--B and B
        8--B and B
        9--A and D
    
  • 相关阅读:
    mTracker ----- MPDP
    读取UIM卡中的短信
    Your version is: java version "1.6.0_24". The correct version is: Java SE 1.6.
    [Java2 入门经典]第14章 集合框架
    [Java2 入门经典]第13章 泛型类
    [Java2 入门经典]第6章 类的扩展与继承
    彩信下载
    指标权重确定方法之熵权法
    用户价值分析
    数据归一化处理
  • 原文地址:https://www.cnblogs.com/gujiewei/p/9670572.html
Copyright © 2011-2022 走看看