• 【Java基础】Java中的多态


    什么是多态

      多态是一个对象的多种实现,是建立在继承的基础上的,即对象“人”,有老师和学生不同的实现,其实总结起来就是允许将子类类型的指针赋值给父类类型的指针。

    多态的发生条件

      多态发生的前提是:1. 要有继承发生; 2. 要有方法的重写; 3. 要有父类引用指向子类对象。

    多态中成员的访问特点

      一个类中有成员变量,构造方法,成员方法和静态方法,那在多态中这些成员的访问特点是如何的呢,下面通过代码来总结下。

    /**
     * Created by lili on 15/10/21.
     */
    
    class Person {
        String name = "person name";
    
        public Person() {
            System.out.println("person construct");
        }
    
        public void show() {
            System.out.println("person show!");
        }
    
        public static void play() {
            System.out.println("person play");
        }
    }
    
    class Student extends Person {
        String name = "Student name";
        String nickName = "young boy";
    
        public Student() {
            System.out.println("student construct");
        }
    
        public void show() {
            System.out.println("student show!");
        }
    
        public static void play() {
            System.out.println("student play");
        }
    
        public void study() {
            System.out.println("student study");
        }
    }
    
    
    public class PolymorphismTest {
        public static void main(String[] args) {
            Person person = new Student();
    
            System.out.println("***********************************");
            System.out.println(person.name);
    
            System.out.println("***********************************");
            person.show();
    
            System.out.println("***********************************");
            person.play();
    
    //        System.out.println("***********************************");
    //        person.study(); //编译报错,找不到符号
    
    //        System.out.println(person.nickName);//编译报错,找不到符号
            
        }
    }

    运行结果如下:

    person construct
    student construct
    ***********************************
    person name
    ***********************************
    student show!
    ***********************************
    person play
    
    Process finished with exit code 0

    对结果进行解释和总结  

      1. 成员变量
        编译看左边,运行看左边。

        如果在父类引用总访问子类特有的成员变量则编译报错,例如System.out.println(person.nickName);//编译报错,找不到符号

        子类和父类都有的,即子类继承的,不管对子类的成员变量如何做变化,最后显示的该成员变量的结果都是对父类成员变量操作后的结果。
      2. 构造方法
        这个是继承中的知识,是分层次初始化的,调用默认构造初始化,即虽然是new的Student,但是是先初始化Person,再初始化Student,所以打印顺序是:

        person construct
        student construct

      3. 成员方法    

        编译看左边,运行看右边。

        编译的时候只能调用父类有的成员方法,调用子类特有的成员方法则报错,这是多态的弊端,不能通过分类引用调用子类非继承成员方法。但是可以向下转型实            现这个功能,下文讲述。

        运行的时候,由于成员方法重写了,所以运行子类中的该方法的具体实现,这点很有意思!所以person.show()最后打印结果是student show;
      4. 静态方法
        编译看左边,运行看左边。
        静态和类相关,算不上重写,所以,访问还是左边的

    多态的好处

      多态的好处在于简化了代码,提供了很好的可扩充性。例如有一个“形状”对象,目前有“圆形”,“长方形”,“正方形”三种实现,在画图的测试方法中,方法的传递参数可以是“形状”类型,你传进来的可以是“圆形”,“长方形”,“正方形”对象,最后调用“形状”来画图,执行的是不同对象的画图方法。如果没有多态,则每个对象都需要专门写一个测试方法来测试,而现在只需要一个了。

    如何访问多态中子类特有成员方法和成员变量:多态中的向下转型和向上转型

      对于子类中的非继承自父类的特有方法和成员变量,例如student中的play方法,肯定有用的,但是如何调用呢?在这里就需要用到向下转型,把父类的引用利用强制类型转换给子类,然后通过这个子类引用去调用。示例程序如下:

    /**
     * Created by lili on 15/10/21.
     */
    
    class Person {
        String name = "person name";
    
        public Person() {
            System.out.println("person construct");
        }
    
        public void show() {
            System.out.println("person show!");
        }
    
        public static void play() {
            System.out.println("person play");
        }
    }
    
    class Student extends Person {
        String name = "Student name";
        String nickName = "young boy";
    
        public Student() {
            super.name = "student modified name";
            System.out.println("student construct");
        }
    
        public void show() {
            System.out.println("student show!");
        }
    
        public static void play() {
            System.out.println("student play");
        }
    
        public void study() {
            System.out.println("student study");
        }
    }
    
    class Teacher extends Person{
    
    }
    
    public class PolymorphismTest {
        public static void main(String[] args) {
            Person person = new Student();
    
            Student student = (Student)person;
            student.study();
    
            Teacher teacher = (Teacher)person;
            teacher.show();
    
    //        System.out.println(person.nickName);//编译报错,找不到符号
    
        }
    }

    运行结果:

    person construct
    student construct
    student study
    Exception in thread "main" java.lang.ClassCastException: Student cannot be cast to Teacher
        at PolymorphismTest.main(PolymorphismTest.java:54)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
    
    Process finished with exit code 1

      向下转型的特点 

         1. 需要用到强制类型转换,将父类强制转型为子类,但是父类指向的对象必须是该子类实例化对象。

         2. 向下转型为父类引用指向子类对象相同的引用,可以实现子类特有方法和成员变量的访问。

      向上转型的特点

        1. 发生在传参或者new子类对象给父类引用的过程中

    多态一个有趣的例子

    /**
     * Created by lili on 15/10/21.
     */
    
    class Person {
    
        public void show() {
            play();
        }
    
        public void play() {
            System.out.println("person play");
        }
    }
    
    class Student extends Person {
    
        public void play() {
            System.out.println("student play");
        }
    }
    
    class Monitor extends Student{
        public void show() {
            super.show();
        }
        public void play() {
            System.out.println("Monitor play");
        }
    }
    
    public class PolymorphismTest {
        public static void main(String[] args) {
            Person person = new Student();
            person.show();//student中没有重写show,所以调用的是person的show()方法,但是show中调用play在student中有重写,所以最后打印student play
    
            System.out.println("------------------");
    
            Student student = (Student) person;
            student.show();
    
            System.out.println("------------------");
    
            student = new Monitor();
            student.show();//monitor中有重写show,所以调用student.show()方法时(student中的show是继承自person),由于monitor有继承,调用monitor
                  //的show()方法,但是monitor中show方法是调用super.show(),super中的show是调用play,最后还是打印Monitor的play } }

    运行结果:

    student play
    ------------------
    student play
    ------------------
    Monitor play
    
    Process finished with exit code 0
  • 相关阅读:
    期权波动率模型及交易策略分析
    k阶原点距和k阶中心距各是说明什么数字特征
    在Linux中监视IO性能
    NUMA微架构
    Web网站的几个QPS
    Elasticsearch与Solr 选型
    相关连接(后续更新)
    linux_基本命令使用(后续更新)
    centos7.5安装kafka(支持外部连接)
    centos7.5单机安装安装zookeeper
  • 原文地址:https://www.cnblogs.com/gslyyq/p/4899864.html
Copyright © 2020-2023  润新知