zoukankan      html  css  js  c++  java
  • 一脚踩进java之基础篇15——面向对象 (多态)

    一、多态的概述

    1.1 多态是继封装、继承之后,面向对象的第三大特性。

    1.2 Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

    1.3 如Student类可以为Person类的子类。那么一个Student对象既可以赋值给一个Student类型的引用,也可以赋值给一个Person类型的引用。

    1.4 总结:

      1)最终多态体现为父类引用变量可以指向子类对象。

      2)多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。

      3)在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。

    二、多态的定义与使用格式

    2.1 多态的定义格式:就是父类的引用变量指向子类对象

    父类类型  变量名 = new 子类类型();
    变量名.方法名();
    接口 变量名 = new 接口实现类();
    变量名.方法();

    三、多态成员的特点

    3.1 多态成员变量

      当子父类中出现同名的成员变量时,多态调用该变量时:

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

      运行时期:也是调用引用型变量所属的类中的成员变量。

      简单记:编译和运行都参考等号的左边。编译运行看左边。

    3.2 多态成员方法

      编译时期:参考引用变量所属的类,如果没有类中没有调用的方法,编译失败。

      运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员方法。

      简而言之:编译看左边,运行看右边。

    四、instanceof关键字

    我们可以通过instanceof关键字来判断某个对象是否属于某种数据类型。如学生的对象属于学生类,学生的对象也属于人类。

    使用格式:

    boolean  b  = 对象  instanceof  数据类型;

            如

    Person p1 = new Student(); // 前提条件,学生类已经继承了人类

    boolean flag = p1 instanceof Student; //flag结果为true

    boolean flag2 = p2 instanceof Teacher; //flag结果为false

    五、多态转型

    多态的转型分为向上转型与向下转型两种:

    5.1  向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。

    使用格式:

    父类类型  变量名 = new 子类类型();
    
    如:Person p = new Student();

    5.2  向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!

    使用格式:

    子类类型 变量名 = (子类类型) 父类类型的变量;
    
    如:Student stu = (Student) p;  //变量p 实际上指向Student对象

    六、多态的好处与弊端

    当父类的引用指向子类对象时,就发生了向上转型,即把子类类型对象转成了父类类型。向上转型的好处是隐藏了子类类型,提高了代码的扩展性。

    但向上转型也有弊端,只能使用父类共性的内容,而无法使用子类特有功能,功能有限制。

    //描述动物类,并抽取共性eat方法
    abstract class Animal {
        abstract void eat();
    }
     
    // 描述狗类,继承动物类,重写eat方法,增加lookHome方法
    class Dog extends Animal {
        void eat() {
            System.out.println("啃骨头");
        }
    
        void lookHome() {
            System.out.println("看家");
        }
    }
    
    // 描述猫类,继承动物类,重写eat方法,增加catchMouse方法
    class Cat extends Animal {
        void eat() {
            System.out.println("吃鱼");
        }
    
        void catchMouse() {
            System.out.println("抓老鼠");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Animal a = new Dog(); //多态形式,创建一个狗对象
            a.eat(); // 调用对象中的方法,会执行狗类中的eat方法
            // a.lookHome();//使用Dog类特有的方法,需要向下转型,不能直接使用
            
            // 为了使用狗类的lookHome方法,需要向下转型
    // 向下转型过程中,可能会发生类型转换的错误,即ClassCastException异常
            // 那么,在转之前需要做健壮性判断 
            if( !a instanceof Dog){ // 判断当前对象是否是Dog类型
                     System.out.println("类型不匹配,不能转换"); 
                     return; 
            } 
            Dog d = (Dog) a; //向下转型
            d.lookHome();//调用狗类的lookHome方法
        }
    }

    我们来总结一下:

    6.1 什么时候使用向上转型:

    当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作,这时就可以使用向上转型。

    如:Animal a = new Dog();

        a.eat();

    6.2 什么时候使用向下转型

    当要使用子类特有功能时,就需要使用向下转型。

        如:Dog d = (Dog) a; //向下转型

            d.lookHome();//调用狗类的lookHome方法

    6.3 向下转型的好处:可以使用子类特有功能。

    6.4 弊端是:需要面对具体的子类对象;在向下转型时容易发生ClassCastException类型转换异常。在转换之前必须做类型判断。

    如:if( !a instanceof Dog){…}

  • 相关阅读:
    QOMO Linux 4.0 正式版发布
    LinkChecker 8.1 发布,网页链接检查
    pgBadger 2.1 发布,PG 日志分析
    Aletheia 0.1.1 发布,HTTP 调试工具
    Teiid 8.2 Beta1 发布,数据虚拟化系统
    zLogFabric 2.2 发布,集中式日志存储系统
    开源电子工作套件 Arduino Start Kit 登场
    Piwik 1.9 发布,网站访问统计系统
    Ruby 1.9.3p286 发布,安全修复版本
    toBraille 1.1.2 发布,Java 盲文库
  • 原文地址:https://www.cnblogs.com/smilehq/p/12831056.html
Copyright © 2011-2022 走看看