• Java基础一篇过(九)面向对象之多态【向上转型与向下转型】


    一、多态的一些基本概念

      简单理解:简而言之就是同一个行为具有多个不同表现形式或形态的能力

    例:比如有一个玻璃杯,当倒入不同的水时,我用手去摸的感觉是不一样的,这就是多态的简单理解。

    多态的分类

    重写式多态

      重载式多态,也叫编译时多态。也就是说这种多态再编译时已经确定好了。重载大家都知道,方法名相同而参数列表不同的一组方法就是重载。在调用这种重载的方法时,通过传入不同的参数最后得到不同的结果。

    重载式多态

      重写式多态,也叫运行时多态。这种多态通过动态绑定(dynamic binding)技术来实现,是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。也就是说,只有程序运行起来,你才知道调用的是哪个子类的方法。

    多态的条件

    • 继承(实现) :在多态中必须存在有继承关系的子类和父类。
    • 重写 :子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
    • 向上转型 :在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

    二、多态的转型

      此篇文章的重点 and 难点来了哈~

    向上转型

      简单理解:子类引用的对象转换为父类类型

      特点:

    • 被子类重写的方法被调用时,调用的是子类方法
    • 子类单独定义的方法丢失
    • 同名属性被子类覆盖

      好处:

    • 减少重复代码,使代码变得简洁。
    • 提高系统扩展性。

      举个栗子:

    /**
     * 动物类【父类】
     */
    public class Animal {
        public void eat() {
            System.out.println("动物吃点啥好呢?");
        }
    }
    /** * 猫类【子类】 */ public class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } }
    /** * 狗类【子类】 */ public class Dog extends Animal { public void eat() { System.out.println("狗吃骨头"); } public void run() { System.out.println("狗会跑"); } }
    /** * 模拟调用 */ public class Main { public static void main(String[] args) { /*1、实例化一个动物,并把猫对象给赋值给动物*/ Animal animal = new Cat(); //向上转型【实例化一个动物,对象为猫】 animal.eat(); /*2、实例化一个动物,并把狗对象给赋值给动物*/ animal = new Dog();//向上转型【实例化一个动物,对象为狗】 animal.eat(); //3、由于向上转型,统一由动物类来调配,此时狗的run()方法是无法直接通过animal.run()调用的,需要强转才可以,这是向上转型的一个特点 ((Dog) animal).run(); } }

    向下转型

      简单理解:把父类对象转为子类对象

      特点:

    • 向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型
    • 向下转型只能转型为本类对象

      作用:

    • 很多时候,我们需要把很多种类的实例对象,全部扔到一个父类集合【向上转型,丢失了一些方法】
    • 再取出来用的时候,就需要强制转换为我们需要的子类对象【向下转型,重新获得丢失的方法】

      PS:详细解析可以看这篇文章,写的很好。

    三、经典多态题解析

    基础类

    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 {
    
    }

    调用类解析

    /**
     * 经典多态解析
     *
     * @author 有梦想的肥宅
     */
    public class Main {
        //已知继承关系:C/D —> B —> A
        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();
    
            //PS:继承链中对象方法的调用的优先级:
         //this.show(obj) ==》 super.show(obj) ==》 this.show((super)obj) ==》super.show((super)obj)
    System.out.println("1、 " + a1.show(b));//A and A【this.show((super)obj)】 System.out.println("2、 " + a1.show(c));//A and A【this.show((super)obj)】 System.out.println("3、 " + a1.show(d));//A and D【this.show(obj)】 System.out.println("4、 " + a2.show(b));//B and A【this.show((super)obj)】 System.out.println("5、 " + a2.show(c));//B and A【this.show((super)obj)】 System.out.println("6、 " + a2.show(d));//A and D【super.show(obj)】 System.out.println("7、 " + b.show(b));//B and B【this.show(obj)】 System.out.println("8、 " + b.show(c));//B and B【this.show((super)obj)】 System.out.println("9、 " + b.show(d));//A and D【super.show(obj)】 } }

      解析:这里我们主要拿出第4条来看,这个例子比较典型,根据注释中“PS”的内容,我们可以分析出以下流程:

    • 1、a2是类型为A的引用类型,它指向类型为B的对象。A确定可调用的方法:show(D obj) 和 show(A obj)
    • 2、a2.show(b) ==> this.show(b),这里this指的是B
    • 3、比较第一级别,在B类中找show(B obj),找到了,可惜没用,因为show(B obj)方法不在可调用范围内【向上转型丢失了方法】,this.show(B obj)失败。
    • 4、进入第二级别:super.show(B obj),super指的是A。 在A 中寻找show(B obj),失败,因为没用定义这个方法。
    • 5、进入第三级别:this.show((super)B obj),this指的是B。 在B中找show(A objA),找到了:show(A objA),选择调用该方法。
    • 6、输出:B and A

    四、小结

    • 多态 :简而言之就是同一个行为具有多个不同表现形式或形态的能力
    • 多态的分类运行时多态编译时多态
    • 运行时多态的前提继承(实现)重写向上转型
    • 继承链中对象方法的调用的优先级
      • 1、this.show( obj ) 
      • 2、super.show( obj ) 
      • 3、this.show((super) obj)
      • 4、super.show((super) obj)

     

     

     

    参考文章:

  • 相关阅读:
    [JS]格式化Date和分析格式化Date字符串的JS代码
    发布一个实用美观的Vista Sidebar Gadget (代表博客园参赛)
    2月8号N706从深圳回湖南,有没有同行的,呵呵
    LiveWriter测试
    自动内容滚动条[WinForm控件]
    关于Ajax的一揽子工程(1)
    “做事先做人”实战
    成熟度即流程
    金秋游故宫
    html块状元素、内联元素
  • 原文地址:https://www.cnblogs.com/riches/p/13753636.html
Copyright © 2020-2023  润新知