zoukankan      html  css  js  c++  java
  • Java 多态

    1、概念

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

    Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。

    多态体现:父类引用变量可以指向子类对象。

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

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

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

    定义格式:

    父类类型  变量名 = new 子类类型();
    变量名.方法名();

    使用格式:

    //普通类多态定义的格式
    父类 变量名 = new 子类();
    //抽象类多态定义的格式
    抽象类 变量名 = new 抽象类子类();
    //接口多态定义的格式
    接口 变量名 = new 接口实现类();

     3、 多态-成员的特点

    l 多态成员变量 

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

    class Fu {
        int num = 4;
    }
    class Zi extends Fu {
        int num = 5;
    }
    class Demo {
        public static void main(String[] args)     {
            Fu f = new Zi();
            System.out.println(f.num);
            Zi z = new Zi();
            System.out.println(z.num);
        }
    }

    l 多态成员方法

    多态调用成员方法访问子类

    class Fu {
        int num = 4;
        void show()    {
            System.out.println("Fu show num");
        }
    }
    class Zi extends Fu {
        int num = 5;
        void show()    {
            System.out.println("Zi show num");
        }
    }
    class Demo {
        public static void main(String[] args)     {
            Fu f = new Zi();
            f.show();
        }
    }

    4、多态-转型

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

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

    使用格式:

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

     向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。

    必须先向上转型才能有向下转型,如果是直接创建父类对象,是无法向下转型的!

    向下转型时,必须先进行判断,用关键词instanceof

    使用格式:

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

    5、 instanceof关键字

    同一个父类会被多个子类继承,所以向下转型时,需要判断是否是属于相应的数据类型(子类引用数据类型)

    instanceof关键字来判断某个对象是否属于某种数据类型,返回值为boolean型

    使用格式: 

    boolean  b  = 对象  instanceof  数据类型; 

    例:

    Person p1 = new Student(); // 前提条件,学生类已经继承了人类
    boolean flag = p1 instanceof Student; //flag结果为true
    boolean flag2 = p1 instanceof Teacher; //flag结果为false

    6、多态的作用

    //描述动物类,并抽取共性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方法 } }

     疑问:为什么要向上转型,向上转型的意义是什么?

    例如:为什么需要 Animal a = new Dog();

    完全可以:Dog a=new Dog();,因为Dog类完全继承Animal的方法

    解析:该例题不够明确,另写一个例题

    public class Testjava {
        public static void main(String args[])
        {
        fun(new Student());
        fun(new Allen());
    
        }
        public static void fun(Person p){ 
            p.fun2();
            if (p instanceof Student){
                Student s=(Student)p;
                s.fun3();
            }if (p instanceof Allen){
                Allen a=(Allen)p;
                a.fungod();
            }
        }
    }

    这个跟java面向对象的特性有关,是多态的表现特点
    public static void fun(Person p)就像你这里的这个参数,如果不用person,而是用student或者allen

    那你这个方法的可利用率就低了。但如果用person,那这个方法既可以匹配student,又可以匹配allen
    再比如你的程序开始的时候确定有一个person型对象,但是要根据用户的选择来决定他要被实例化成哪种类型的。但如果你要分开来声明的话,那你就因为不确定性必须要声明两个变量,分别来等待实例化。

    你这个程序里就只有public static void fun(Person p)这一个方法,如果说是分成两个单独的类,要改的话就只需要改这一个参数。。。。
    但是后面做大程序的时候,往往好几十个方法,如果你不用person,而用了student,那你一旦在写程序的时候发现这里应该用allen而不是student,而你又没用person,那你这里一改就要改N多的地方,而且一改动很有可能会引发其他的错误,而且你这些方法很有可能又被其他的类所调用,那其他的类肯定也要跟着改啊,那这个改动量就非常大了。
    比如说你的public static void fun(Student p)要传进来一个Allen类型的对象,必然报错,要改是吧~

    但是如果你使用的person,那你只需要改动它实例化的语句就ok了,上面这么大的改动量现在只需要改一句话。
    就是将
    Person p=new Student();
    改为
    Person p=new Allen();
    而你其他具体的方法啊,其他的相关类的代码都不用改!这就是他的意义。“

    本文是引用自百度知道的一个问题和解答。

  • 相关阅读:
    201671010112 第十四周 Swing用户界面组件
    201671010112 第十二周
    201671010112 第十二周—— “如何在eclipse中重定向标准输入到文件?”整理方案
    201671010112 第十一周
    201671010112 第十周
    201671010112 第九周
    201671010112 第八周
    201671010112 第六周
    面向对象的程序设计课程进度
    201671010111 2016-2017-2《面向对象的程序设计》 java学习总结
  • 原文地址:https://www.cnblogs.com/dk2557/p/9397131.html
Copyright © 2011-2022 走看看