点我

案例

编写一个程序,Master类中有一个feed(喂食)的方法,可以完成主人对动物喂食物的操作。

代码
food类

package com.xbxaq.poly_;

public class Food {
    private String name;

    public Food(String name){
        this.name = name;
    }
    public String getName() {
        return name;
    }

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

fish类

package com.xbxaq.poly_;

public class Fish  extends Food{
    public Fish(String name){
        super(name);
    }
}

bone类

package com.xbxaq.poly_;

public class Bone extends Fish{
    public Bone(String name){
        super(name);
    }
}

animal类

package com.xbxaq.poly_;

public class Animal {
    private String name;
    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

dog类

package com.xbxaq.poly_;

public class Dog extends Animal{
    public Dog(String name) {
        super(name);
    }
}

cat类

package com.xbxaq.poly_;

public class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
}

master类

package com.xbxaq.poly_;

public class Master {
    private String name;

    public Master(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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


    // 完成主人对小狗的喂食效果
    public void feed(Dog dog, Bone bone){
        System.out.println("主人 " + name + " 给" + dog.getName() + "喂 " + bone.getName());
    }
}

poly类

package com.xbxaq.poly_;

public class Poly01 {
    public static void main(String[] args) {
        Master tom = new Master("tom");
        Dog dog = new Dog("小白");
        Bone bone = new Bone("大白骨");
        tom.feed(dog, bone);
    }
}

运行结果

基本概述

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

多态的具体体现

1、方法的多态(重载与重写)
2、对象的多态

一个对象的编译类型和运行类型可以不一致。
编译类型在定义对象时,就确定了,不能改变
允许类型是可以变化的
编译类型看定义时 =号的左边,运行类型看 =号的右边

多态的细节

1、多态的前提是:两个对象(类)存在继承关系
2、多态的向上转型,本质为父类的引用指向了子类的对象

语法:父类类型    引用名  =  new  子类类型()
特点:编译类型看右边,运行类型看左边
可以调用父类的所有成员(需遵守访问权限),不能调用子类的特有成员。

3、多态的向下转型

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

4、属性没有重写之说,属性的值看编译类型

animal类

cat类

Detail类

结果

动态绑定机制

  • 当调用对象方法时,该方法会和对象的内存地址[也就是运行类型]进行绑定
  • 当调用对象属性时,没有动态绑定机制,哪里声明哪里使用
示例代码-1
public class BangDing{
    public static void main(String args[]){
    A a = new B();
    System.out.println(a.sum());
    System.out.println(a.sum1());
    }
}

class A{
    public int i = 10;
    public int sum(){
        return getl() + 10;
    }
    public int sum1(){
        return i + 10;
    }
    public int getl(){
        return i;
    }
}

class B extends A {
    public int i = 20;
    public int sum(){
        return i + 20;
    }
    public int getl(){
        return i;
    }
    public int sum1(){
        return i + 10;
    }
}

image-20240228170629776

代码示例-2
public class BangDing{
    public static void main(String[] args){
    A a = new B();
    System.out.println(a.sum());
    System.out.println(a.sum1());
    }
}

class A{
    public int i = 10;
    public int sum(){
        return getl() + 10;
    }
    public int sum1(){
        return i + 10;
    }
    public int getl(){
        return i;
    }
}

class B extends A {
    public int i = 20;
//    public int sum(){
//        return i + 20;
//    }
    public int getl(){
        return i;
    }
    public int sum1(){
        return i + 10;
    }
}

image-20240228171648042

代码示例-3
public class BangDing{
    public static void main(String[] args){
    A a = new B();
    System.out.println(a.sum());
    System.out.println(a.sum1());
    }
}

class A{
    public int i = 10;
    public int sum(){
        return getl() + 10;
    }
    public int sum1(){
        return i + 10;
    }
    public int getl(){
        return i;
    }
}

class B extends A {
    public int i = 20;
//    public int sum(){
//        return i + 20;
//    }
    public int getl(){
        return i;
    }
//    public int sum1(){
//        return i + 10;
//    }
}

image-20240228171847770

多态数组

  • 多态数组:数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
应用实例-1

现有一继承结构,要求创建一个person对象、两个student对象和两个teacher对象,统一放在数组中,并调用每个对象的say方法。

image-20240228172630018

plaoarray类

public class PloyArray{
     public static void  main(String[] args){
        Person[] person = new Person[5];
        person[0] = new Person("zhangsan",30);
        person[1] = new Student("wangwu",18,74.0);
        person[2] = new Student("wangpeng",17,89.5);
        person[3] = new Teacher("zhangxiwang",32,15000);
        person[4] = new Teacher("luoping",32,20000);

        //遍历多态数组调用say方法
         for (int i = 0; i < person.length; i++) {
             System.out.println(person[i].say()); //动态绑定机制
         }
     }
}

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;
    }

}


teacher类

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(){
        this.salary = salary;
    }

    @Override
    public String say() {
        return super.say() + " salary=" + salary;
    }
}

student类

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方法
    public String say(){
         return super.say() + " score=" + score;
    }


}

运行效果

image-20240228180002395

应用实例-2

如何调用子类特有的方法,例如:teacher类有一个teach方法,student类有一个study方法,该如何调用呢

plaoarray类

public class PloyArray{
     public static void  main(String[] args){
        Person[] person = new Person[5];
        person[0] = new Person("zhangsan",30);
        person[1] = new Student("wangwu",18,74.0);
        person[2] = new Student("wangpeng",17,89.5);
        person[3] = new Teacher("zhangxiwang",32,15000);
        person[4] = new Teacher("luoping",32,20000);

        //遍历多态数组调用say方法
         for (int i = 0; i < person.length; i++) {
             System.out.println(person[i].say()); //动态绑定机制
             if (person[i] instanceof Teacher){
                 ((Teacher)person[i]).teach();
             }

             if (person[i] instanceof Student){
                 ((Student)person[i]).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;
    }

}


teacher类

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(){
        this.salary = salary;
    }

    @Override
    public String say() {
        return super.say() + " salary=" + salary;
    }
    public void teach(){
        System.out.println("教师:" + getName());
    }
}

student类

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方法
    public String say(){
         return super.say() + " score=" + score;
    }

    public void study(){
        System.out.println("学生" + getName());
    }
}

运行效果

image-20240228181031556

多态参数

  • 多态参数:方法定的形参类型为父类类型,实参类型允许为子类类型
实例

需求:定义员工类Employee其中包含姓名name、月工资[private]以及计算年工资的getAnnual方法,普通员工和经理继承了员工,经理类多了奖金bonus属性和管理manage方法,普通员工类多了work方法,普通员工和经理类要求分别重写getAnnual方法

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

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

Employee类

public class Employee{
    private String name;
    private Double salary;


    // 年工资
    public double getAnnual(){
        return  12 * salary;
    }

    public Employee(String name, Double salary){
        this.name = name;
        this.salary = salary;
        }
    public String getName(){
        return  name;
    }
    public Double getSalary(){
        return salary;
    }

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

}

worker类

public class Worker extends Employee{
    public Worker(String name,double salary){
        super(name,salary);
    }
    public void work(){
        System.out.println("员工" + getName() + "正在工作");
    }
    public double getAnnual(){
        return  super.getAnnual();
    }


}

manager类

public class Manager extends  Employee{
    private double bonus;
    public void manage(){
        System.out.println("经理" + getName() + "正在管理");
    }
    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 double getAnnual(){
        return  super.getAnnual() + bonus;
    }
}

PloyParameter类

public class PloyParameter{
    public static void main(String[] args){
        Worker tom = new Worker("tom",10.0);
        Manager zhangsan = new Manager("zhangsan",7000,10000);
        PloyParameter ployParameter = new PloyParameter();
        ployParameter.showEmpAnnual(tom);
        ployParameter.showEmpAnnual(zhangsan);
        ployParameter.testWork(tom);
        ployParameter.testWork(zhangsan);

    }


    //添加一个方法showEmpAnnual(employee)

    public void  showEmpAnnual(Employee e){
        System.out.println(e.getAnnual());
    }


    // 添加一个方法testWork,如果是普通员工,则调用testWork方法,如果是经理则调用manage方法
    public void testWork(Employee e){
        if (e instanceof Worker){
            ((Worker) e).work();
        }else if(e instanceof Manager){
            ((Manager) e).manage();
        }


    }
}

运行效果

image-20240228215448181

细节讨论

属性看编译类型,方法看运行类型

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

代码

public class a1{
    public static void main(String[] args){
        Base base = new Sub();
        System.out.println(base.count);

        Sub sub = new Sub();
        System.out.println(sub.count);
    }
}

class Base{
    int count = 10;
}

class Sub extends Base{
    int count = 20;
}

image-20240228152656794

instanceOf比较操作符,用于判断对象的运行类型是否为xx类型或者xx类型的子类型
public class a1{
    public static void main(String[] args){
    Sub sub = new Sub();
    System.out.println(sub instanceof Sub);
    System.out.println(sub instanceof Base);

    }
}

class Base{

}

class Sub extends Base{

}

image-20240228163659097

分类: JAVA

评论

-- 评论已关闭 --

目录