zoukankan      html  css  js  c++  java
  • 【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
  • 相关阅读:
    VIJOS-P1340 拯救ice-cream(广搜+优先级队列)
    uva 11754 Code Feat
    uva11426 GCD Extreme(II)
    uvalive 4119 Always an Interger
    POJ 1442 Black Box 优先队列
    2014上海网络赛 HDU 5053 the Sum of Cube
    uvalive 4795 Paperweight
    uvalive 4589 Asteroids
    uvalive 4973 Ardenia
    DP——数字游戏
  • 原文地址:https://www.cnblogs.com/gslyyq/p/4899864.html
Copyright © 2011-2022 走看看