• Java 多态具体指什么?怎么使用多态?


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

    多态的具体体现

    1) 方法的多态(重写和重载就体现多态)

    2)对象的多态 (核心,困难,重点)

    ● 方法的多态案例

    public class PloyMethod {
        public static void main(String[] args) {
            //方法重载体现多态
            A a = new A();
            //这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态
            System.out.println(a.sum(10, 20));
            System.out.println(a.sum(10, 20, 30));
            //方法重写体现多态
            B b = new B();
            a.say();
            b.say();
        }
    }
    
    class B { //父类
        public void say() {
            System.out.println("B say() 方法被调用...");
        }
    }
    
    class A extends B {//子类
    
        public int sum(int n1, int n2) {//和下面 sum 构成重载
            return n1 + n2;
        }
    
        public int sum(int n1, int n2, int n3) {
            return n1 + n2 + n3;
        }
    
        public void say() {
            System.out.println("A say() 方法被调用...");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

    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;//属性
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    ● 对象的多态案例

    (1)一个对象的编译类型和运行类型可以不一致
    (2)编译类型在定义对象时,就确定了,不能改变
    (3)运行类型是可以变化的.
    (4)编译类型看定义时=号的左边,运行类型看=号的右边

    Animal animal = new Dog(); 【animal编译类型是Animal,运行类型Dog】

    animal = new Cat();【animal的运行类型变成了Cat,编译类型仍然是 Animal)

    定义Animal类

    public class Animal {
        public void cry() {
            System.out.println("Animal cry()动物在叫....");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    定义Dog和Cat类继承分别Animal类

    public class Dog extends Animal {
        @Override
        public void cry() {
            System.out.println("Dog cry() 小狗汪汪叫...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class Cat extends Animal {
        @Override
        public void cry() {
            System.out.println("Cat cry() 小猫喵喵叫...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    多态注意事项和细节讨论

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

    ◆ 多态的向上转型

    1)本质:父类的引用指向了子类的对象
    2)语法:父类类型 引用名= new子类类型();
    3)特点:编译类型看左边,运行类型看右边。可以调用父类中的所有成员(需遵守访问权限).不能调用子类中特有成员;
    最终运行效果看子类的具体实现!

      //向上转型:父类的引用指向了子类的对象
      //语法: 父类类型 引用名 = new 子类类型();
      Animal animal = new Cat();
      Object object = new Cat();//可以吗? 可以 Object也是 Cat 的父类
    
      //(1)可以调用父类中的所有成员
      //(2)不能调用子类中特有成员;
      //(3)因为在编译阶段,能调用那些成员,是由编译类型来决定的
      //animal.catchMouse();错误
      //最终运行效果看子类的具体实现
      //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法
      // 然后调用,规则我前面我们讲的方法调用规则一致。
      animal.eat();//猫吃鱼..
      animal.run();//跑
      animal.show();//hello,你好
      animal.sleep();//睡
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ◆ 多态向下转型

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

      //多态的向下转型
      //1)语法:子类类型引用名=(子类类型)父类引用;
      //2)只能强转父类的引用,不能强转父类的对象
      //3)要求父类的引用必须指向的是当前目标类型的对象
      //4)当向下转型后,可以调用子类类型中所有的成员
      Cat cat = (Cat) animal;
      cat.catchMouse();
      cat.eat();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    instanceOf 比较操作符

    instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型

    public class PolyDetail03 {
        public static void main(String[] args) {
            BB bb = new BB();
            System.out.println(bb instanceof BB);// true
            System.out.println(bb instanceof AA);// true
            //aa 编译类型 AA, 运行类型是 BB
            //BB 是 AA 子类
            AA aa = new BB();
            System.out.println(aa instanceof AA);
            System.out.println(aa instanceof BB);
            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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    多态的应用

    1) 多态数组

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

    应用实例:现有一个继承结构如下:

    要求创建 1 个 Person 对象、2 个 Student 对象和 2 个Teacher 对象, 统一放在数组中,并调用每个对象say 方法. 应用实例升级:如何调用子类特有的方法,比如
    Teacher 有一个 teach , Student 有一个 study
    怎么调用?

    定义 Person 类

    public class Person {//父类
        private String name;
        private int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        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;
        }
    
        public String say() {
            return name + "\t" + age;//返回名字和年龄
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    定义 Student 继承 Person 类

    public class Student extends Person {
        private double score;
        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;
        }
        //重写父类的say()
    
        @Override
        public String say() {
            return "学生 "+super.say()+" score="+score;
        }
        //特有方法
        public void study(){
            System.out.println("学生 "+ getName()+" 正在学Java课程...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    定义 Teacher 继承 Person 类

    public class Teacher extends Person{
        private double salary;
        public Teacher(String name, int age,double salary) {
            super(name, age);
            this.salary = salary;
        }
    
        public double getSalary() {
            return salary;
        }
    
        public void setSalary(double sal) {
            this.salary = sal;
        }
        //重写父类的say()
    
        @Override
        public String say() {
            return "老师 "+super.say()+" sal="+salary;
        }
    
        public void teach(){
            System.out.println("老师 "+ getName()+"  正在讲Java课程...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    定义 PloyArray 进行方法调用

    public class PloyArray {
        public static void main(String[] args) {
            Person[] persons = new Person[5];
            persons[0] = new Person("jack", 20);
            persons[1] = new Student("marry", 18, 100);
            persons[2] = new Student("smith", 19, 30.1);
            persons[3] = new Teacher("scott", 30, 20000);
            persons[4] = new Teacher("king", 50, 50000);
    
            for (int i = 0; i < persons.length; i++) {
                if (persons[i] instanceof Student){
    //                Student students = (Student)persons[i];
    //                students.study();
                    ((Student)persons[i]).study();
                }else if (persons[i] instanceof Teacher){
                    ((Teacher)persons[i]).teach();
                }else if (persons[i] instanceof Person){
    
                }else {
                    System.out.println("你的类型有误,请自己检查");
                }
                persons[i].say();
                System.out.println(persons[i].say());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2)多态参数

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

    定义员工类Employee,包含姓名和月工资[private],以及计算年工资getAnnual的方法。

    普通员工和经理继承了员工,经理类多了奖金bonus属性和管理manage方法,普通员工类多了work方法,普通员工和经理类要求分别重写getAnnual方法

    测试类中添加一个方法showEmpAnnual(Employee e),实现获取任何员工对象的年工资,并在main方法中调用该方法[e.getAnnual()]

    测试类中添加一个方法,testWork,如果是普通员工,则调用work方法,如果是经理,则调用manage方法

    定义 Employee 类

    public class Employee {
        private String name;
        private double salary;
    
        public Employee(String name, double salary) {
            this.name = name;
            this.salary = salary;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getSalary() {
            return salary;
        }
    
        public void setSalary(double salary) {
            this.salary = salary;
        }
    
        public double getAnnual(){
            return 12 * salary;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    定义 Manager 继承 Employee

    public class Manager extends Employee {
        private double bonus;
    
        public Manager(String name, double salary, double bonus) {
            super(name, salary);
            this.bonus = bonus;
        }
    
        public double getBonus() {
            return bonus;
        }
    
        public void setBonus(double bonus) {
            this.bonus = bonus;
        }
    
        public void Manager() {
            System.out.println("经理 " + getName() + " is managing");
        }
    
        @Override
        public double getAnnual() {
            return super.getAnnual() + bonus;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    定义 Worker 继承 Employee

    public class Worker extends Employee{
    
        public Worker(String name, double salary) {
            super(name, salary);
        }
    
        public void work(){
            System.out.println("普通员工 "+getName()+" is working");
        }
    
        @Override
        public double getAnnual() {//因为普通员工没有其他的收入,则直接调用父类方法
            return super.getAnnual();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    定义 PloyParameter 调用方法

    public class PloyParameter {
        public static void main(String[] args) {
            Worker tom = new Worker("tom", 2500);
            Manager milan = new Manager("milan", 5000, 20000);
            PloyParameter ployParameter = new PloyParameter();
            ployParameter.showEmpAnnual(tom);
            ployParameter.tetWork(tom);
            ployParameter.showEmpAnnual(milan);
            ployParameter.tetWork(milan);
        }
    
        public void showEmpAnnual(Employee e) {
            System.out.println(e.getAnnual());
        }
    
        public void tetWork(Employee e) {
            if (e instanceof Worker) { //向下转型
                ((Worker) e).work();
            } else if (e instanceof Manager) { //向下转型
                ((Manager) e).Manager();
            }else {
                System.out.println("不做处理");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    k8s修改集群IP--不重置集群
    【COMP305 LEC6 LEC 7】
    【特征选择】基于二进制粒子群算法的特征选择方法(GRNN广义回归神经网络分类)【Matlab代码#32】
    【linux】——程序地址空间_终
    右旋酮洛芬-β-环糊精微球|聚苹果酸-羟喜树碱前药(PMLA-HCPT)|Gd2O3/CuS复合白蛋白纳米粒(科研级)
    ASP.NET Core 6框架揭秘实例演示[25]:配置与承载环境的应用
    高等教育学:教学组织形式与教学工作基本环节
    使用gtest和lcov测试代码覆盖率
    CSS三栏布局的7种方式代码详解 | 圣杯布局 | 双飞翼布局 | 弹性盒子
    应该继续学习编程,还是学数控?
  • 原文地址:https://blog.csdn.net/weixin_46665411/article/details/126268765