JAVA 多态

多态

好处:可以解决代码复用性不高,并且不利于代码维护的问题

一、基本介绍

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

二、对象的多态

以下几个规则要记住,非常重要

  1. 一个对象的编译类型和运行类型可以不一致

    Animal animal = new Dog();//Animal 是编译类型,运行类型是dog
    animal = new Cat(); //animal 的运行类型变成了Cat,编译类型仍然是Animal
    
  2. 编译类型在定义对象时,就确定了,不能改变

  3. 运行类型是可以变化的

  4. 编译类型看定义时 = 号 的左边,运行类型 看 = 号的右边

三、注意事项

多态的前提是:两个对象(类)存在继承关系

  1. 属性没有重写之说!属性的值看编译类型

    package com.hspedu.poly_.detail_;
    
    public class PolyDetail02 {
        public static void main(String[] args) {
            //属性没有重写之说!属性的值看编译类型
            Base base= new Sub();
            System.out.println(base.count);//10
    
            Sub sub = new Sub();
            System.out.println(sub.count);//20
        }
    }
    
    class Base{ //父类
        int count = 10;
    }
    
    class Sub extends Base{
        int count = 20;//属性
    }
    
    
  2. instanceOf比较运算符,用于判断对象的类型是否是XXX类型或者XXX类型的子类型

    package com.hspedu.poly_.detail_;
    
    public class PolyDetail03 {
        public static void main(String[] args) {
            BB bb = new BB();
            System.out.println(bb instanceof BB);
            System.out.println(bb instanceof AA);//true
            //bb是AA嘛或者AA的类型的子类
    
            //编译类型:AA
            //运行类型:BB
            AA aa = new BB();
            System.out.println(aa instanceof  BB);//true
            //这里看的是运行类型而不是编译类型
            System.out.println(aa instanceof AA);//true
    
            Object obj = new Object();
            System.out.println(obj instanceof AA);//false
            String str = "hello";
    //        System.out.println(str instanceof AA);
            System.out.println(str instanceof Object);//true
        }
    }
    
    class AA{//父类
    
    }
    
    class BB extends AA{
    
    }
    
    

1.多态的向上转型

  1. 本质:父类的引用指向了子类的对象

  2. 语法:父类类型 引用名 = new 子类类型();

  3. 特点:编译类型看左边,运行类型看右边。可以调用父类中的所有成员(需遵守访问权限),不能调用子类的特有成员,最终效果要看子类的具体实现(方法会重写)

    • 因为在编译阶段,能调用哪些成员,是由编译类型来决定的
    • 即调用方法时,按照从运行类型(子类)开始查找方法然后调用

    Animal

    package com.hspedu.poly_.detail_;
    
    public class Animal {
        String name = "动物";
        int age = 10;
    
        public void sleep(){
            System.out.println("睡");
        }
    
        public void run(){
            System.out.println("跑");
        }
        public void eat(){
            System.out.println("吃");
        }
        private void show(){
            System.out.println("hello,你好");
        }
    }
    

    cat

    package com.hspedu.poly_.detail_;
    
    public class Cat extends Animal{
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    
        public void catchMouse(){//Cat特有的方法
            System.out.println("猫抓老鼠");
        }
    }
    
    

    main

    package com.hspedu.poly_.detail_;
    
    public class PolyDetail {
        public static void main(String[] args) {
    
            //本质:(向上转型)父类的引用指向子类的对象
            //格式:父类类型 引用名 = new 子类类型();
            Animal animal= new Cat();
            Object obj = new Cat();
    
            //可以调用父类中的所有成员(需遵守访问权限),但是不能调用子类的特有成员
            //animal.catchMouse;不能调用
            //因为在编译阶段,能调用哪些成员,是由编译类型来决定的
            animal.eat();
        }
    }
    

2.多态的向下转型

  1. 语法:子类类型 引用名 = (子类类型) 父类引用;
  2. 只能强转父类的引用,不能强转父类的对象
  3. 要求父类的引用必须指向的是当前目标类型的对象
  4. 当向下转型后,就可以调用子类类型中的所有成员

四、JAVA的动态绑定机制

注意:非常非常重要

  1. 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
  2. 当调用对象属性的时候,没有动态绑定机制,哪里声明,哪里使用,遵循作用域的原则
package com.hspedu.poly_.dynamic_;

public class DynamicBinding {
    public static void main(String[] args) {
        //编译类型:A,运行类型:B
        A a = new B();
        System.out.println(a.sum());//40 -> 30
        System.out.println(a.sum1());//30 -> 20
    }
}

class A {
    public int i = 10;

    //动态绑定机制:
    //1.当调用
    public int sum() {
        return getI() + 10;//调用子类的getI(),20+10
    }

    public int sum1() {
        return i + 10;//10+10
    }

    public int getI() {
        return i;
    }
}

class B extends A {
    public int i = 20;

    /*    public int sum(){
            return i+20;
        }*/
    public int getI() {
        return i;
    }

/*    public int sum1() {
        return i + 10;
    }*/
}

五、多态的应用

1.多态数组

数组的定义类型为父类类型,里面保存的实际元素类型为子类类型

Person:父类

package com.hspedu.poly_.polyarr_;

public class Person {
    private String name;
    private int age;

    public String say(){
        return "name="+name + "\nage="+age;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void person(){
        System.out.println("群众"+name);
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Student

package com.hspedu.poly_.polyarr_;

public class Student extends Person{
    private double score;

    //重写say方法
    @Override
    public String say() {
        return "学生\n"+super.say() + "\nscore=" + score;
    }

    public void study(){
        System.out.println("学生" + getName() + "正在学JAVA课程");
    }

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}

Teacher

package com.hspedu.poly_.polyarr_;

public class Teacher extends Person{
    private double salary;

    @Override
    public String say() {
        return "老师\n"+super.say()+"\nsalary="+salary;
    }

    public void teach(){
        System.out.println("老师" + getName() + "正在讲JAVA课程");
    }
    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

2.多态参数

方法定义的形参类型为父类类型,实参类型允许为子类类型

posted @ 2022-02-03 19:57  DL50  阅读(50)  评论(0编辑  收藏  举报