文章目录

  • 1 多态数组
  • 1.1 需求变更
  • 1.2 instanceof 介绍
  • 1.3 使用 instanceof 完成需求
  • 1.4 *完整代码
  • 2 多态参数
  • 写在最后



1 多态数组

✈️ 多态数组是面向对象中的多态的常用点,我们来看下面这个案例:

编写三个类,Person类、Teacher类、Student类,其中 Teacher 与 Student类 均为 Person类的子类。具体要求如下:
(1)在 Person类 中,包含 name,用于存储人的姓名;
(2)在 Teacher类 中,额外需要一个 salary属性,用于记录老师的月工资;
(3)在Student类 中,额外需要一个 score属性,用于存储学生的成绩;
(4) 以上三个类均需要提供一个 say() 方法,用于展示基本信息;
(5) 录入2个老师以及3个学生的信息,并输出结果。

通过分析需求,我们可以确定继承关系如下图:

java实现多对象数组 java多态数组_java


🍑 参考代码如下:

为了方便起见,没有编写相应的 set 和 get 方法,只简单实现了构造器。

public class PolyArray {
    public static void main(String[] args) {
         Person[] person = new Person[5];
         // 录入两个老师和三个学生的信息
         person[0] = new Teacher("王芳", 4800);
         person[1] = new Teacher("陈冰冰", 6500);
         person[2] = new Student("霸王龙", 95);
         person[3] = new Student("毛毛虫", 98);
         person[4] = new Student("臭贝", 88);
         // 信息展示
        for (int i = 0; i < person.length; i++) {
            System.out.println(person[i].say());  // 由多态的特性知,会根据运行类型调用相应的方法
        }
    }
}

/**
 *  Person类
 */
class Person{
    private String name;  // 存储姓名

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

    // 展示信息的方法
    public String say(){
        return "我是" + name;
    }
}

/**
 *  Teacher类
 */
class Teacher extends Person{
    private int salary;  // 存储工资

    public Teacher(String name, int salary) {
        super(name);
        this.salary = salary;
    }

    // 重写 say 方法
    @Override
    public String say(){
        return super.say() + ", " + "薪水是" + salary + "RMB";
    }
}

/**
 *  Student类
 */
class Student extends Person{
    private int score;  // 记录学生成绩

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

    // 重写 say 方法
    @Override
    public String say(){
        return super.say() + ", " + "成绩是" + score;
    }
}

🍎 实现结果:

java实现多对象数组 java多态数组_多态_02

1.1 需求变更

1 小节的功能我们已经通过多态的方式实现了,现在,突然有了个新需求:

(1)在 Teacher 类中添加新方法 teach,用于展示教师授课的行为;
(2)在 Student 类中添加新方法 study,用于展示学生听课的行为。

🍑 根据新的需求,我们分别在 Teach 类 与 Student 类中添加新的方法:
⭐️ Teacher 类:

class Teacher extends Person{
    private int salary;  // 存储工资

    public Teacher(String name, int salary) {
        super(name);
        this.salary = salary;
    }

    // 重写 say 方法
    @Override
    public String say(){
        return super.say() + ", " + "薪水是" + salary + "RMB";
    }
    
    // 新增加的 teach方法
    public void teach(){
        System.out.println("我在讲课!");
    }
}

⭐️ Student类:

class Student extends Person{
    private int score;  // 记录学生成绩

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

    // 重写 say 方法
    @Override
    public String say(){
        return super.say() + ", " + "成绩是" + score;
    }
    
    // 新增 study 方法
    public void study(){
        System.out.println("我在学习!");
    }
}

好啦,现在我们在主函数中调用一下吧!可是出现了如下的状况:

java实现多对象数组 java多态数组_java_03


❤️ 回顾下上篇博客的相关知识:多态的特性与向下转型 我们发现了问题:teachstudy 两个方法在 Person类中没有声明,属于子类的特有方法,不可以通过父类引用去调用子类的特有成员!!! 因此,如果我们想要完成需求的话,就需要使用到向下转型!可是,在上一节中,博主就介绍了:要求父类的引用必须指向的是当前目标类型的对象,才可以进行向下转型!

😗 那么有没有一种方便的办法,让我们判断可不可以进行向下转型呢?当然!下面我们引入 instanceof 关键字。

1.2 instanceof 介绍

🅰️ instanceof 是 Java 的保留关键字,它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型
值得一提的是: instanceof 实际上是用于判断对象的类型是否为 XX 类型或者 XX类型的 子类型。
🍑 我们来看下面的代码例子,答案在注释,继承关系为 Dog 和 Cat 为 Animal 的子类:

public class Main {
    public static void main(String[] args) {
        Animal a1 = new Animal();
        Animal a2 = new Dog();
        Animal a3 = new Cat();
        Dog d1 = new Dog();
        System.out.println(a1 instanceof Animal); // true
        System.out.println(a1 instanceof Dog);  // false
        System.out.println(a1 instanceof Cat);  // false
        System.out.println(a2 instanceof Animal);  // true
        System.out.println(a2 instanceof Dog);  // true
        System.out.println(a2 instanceof Cat);  // false
        System.out.println(a3 instanceof Animal);  // true
        System.out.println(a3 instanceof Dog);  // false
        System.out.println(a3 instanceof Cat);  // true
        System.out.println(d1 instanceof Animal);  // true
    }
}

1.3 使用 instanceof 完成需求

学习完 instanceof 后,我们就可以在主函数中判断是否可以进行向下转型,以此来调用相应的特有方法啦,主函数修改如下:

public class PolyArray {
    public static void main(String[] args) {
         Person[] person = new Person[5];
         // 录入两个老师和三个学生的信息
         person[0] = new Teacher("王芳", 4800);
         person[1] = new Teacher("陈冰冰", 6500);
         person[2] = new Student("霸王龙", 95);
         person[3] = new Student("毛毛虫", 98);
         person[4] = new Student("臭贝", 88);
         // 信息展示
        for (int i = 0; i < person.length; i++) {
            System.out.println(person[i].say());  // 先展示信息
            if(person[i] instanceof Teacher){  // 如果是老师
                ((Teacher) person[i]).teach();
            } else if(person[i] instanceof Student){  // 如果是学生
                ((Student) person[i]).study();
            } else {  // 其他情况
                System.out.println("Person[" + i + "] 的类型不兼容!");
            }
        }
    }
}

🍎 来看看运行结果:

java实现多对象数组 java多态数组_java_04

1.4 *完整代码

public class PolyArray {
    public static void main(String[] args) {
         Person[] person = new Person[5];
         // 录入两个老师和三个学生的信息
         person[0] = new Teacher("王芳", 4800);
         person[1] = new Teacher("陈冰冰", 6500);
         person[2] = new Student("霸王龙", 95);
         person[3] = new Student("毛毛虫", 98);
         person[4] = new Student("臭贝", 88);
         // 信息展示
        for (int i = 0; i < person.length; i++) {
            System.out.println(person[i].say());  // 先展示信息
            if(person[i] instanceof Teacher){  // 如果是老师
                ((Teacher) person[i]).teach();
            } else if(person[i] instanceof Student){  // 如果是学生
                ((Student) person[i]).study();
            } else {  // 其他情况
                System.out.println("Person[" + i + "] 的类型不兼容!");
            }
        }
    }
}

/**
 *  Person类
 */
class Person{
    private String name;  // 存储姓名

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

    // 展示信息的方法
    public String say(){
        return "我是" + name;
    }
}

/**
 *  Teacher类
 */
class Teacher extends Person{
    private int salary;  // 存储工资

    public Teacher(String name, int salary) {
        super(name);
        this.salary = salary;
    }

    // 重写 say 方法
    @Override
    public String say(){
        return super.say() + ", " + "薪水是" + salary + "RMB";
    }

    // 新增加的 teach方法
    public void teach(){
        System.out.println("我在讲课!");
    }
}

/**
 *  Student类
 */
class Student extends Person{
    private int score;  // 记录学生成绩

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

    // 重写 say 方法
    @Override
    public String say(){
        return super.say() + ", " + "成绩是" + score;
    }

    // 新增 study 方法
    public void study(){
        System.out.println("我在学习!");
    }
}

2 多态参数

✈️ 方法定义的形参类型为父类类型,实参类型允许为子类类型。
Tips:其实就和之前说过的喂养宠物的问题一样!我们来回顾一下,并进行讲解:

尝试用你现有的知识,编写 Food类、 Animal类,并按照下图编写其相应的子类,提供必要的属性。最后,编写一个 Master类,包含喂养宠物的 feed() 方法。请你随意录入一组信息,并测试功能是否实现。

java实现多对象数组 java多态数组_多态_05

🍑 代码如下:

  • ⭐️ Food类:
public class Food {
    private String name;  // 食物名称

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

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

    public String getName() {
        return name;
    }
}
  • ⭐️ Fish类:
public class Fish extends Food{
    public Fish(String name) {
        super(name);
    }
}
  • ⭐️ Bone类:
public class Bone extends Food{
    public Bone(String name) {
        super(name);
    }
}
  • ⭐️ Animal类:
public class Animal {
    private String name;  // 动物名字

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

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

    public String getName() {
        return name;
    }
}
  • ⭐️ Dog类:
public class Dog extends Animal{
    public Dog(String name) {
        super(name);
    }
}
  • ⭐️ Cat类:
public class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
}
  • ⭐️ Master类:
public class Master {
    private String name;  // 名字

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

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

    public String getName() {
        return name;
    }
    
  	public void feed(Animal animal, Food food){
		System.out.println("主人 " + name + " 给 " + animal.getName() + " 吃 " + food.getName());
	}
}
  • ⭐️ Main测试类:
public class Main {
    public static void main(String[] args) {
        // 领养宠物
        Dog dog = new Dog("大黄狗");
        Cat cat = new Cat("小花猫");
        // 登记主人信息
        Master master = new Master("祢豆子");
        // 提供食物
        Bone bone = new Bone("炸排骨");
        Fish fish = new Fish("小黄鱼");
        // 喂养大黄狗
        master.feed(dog, bone);
        // 喂养小花猫
        master.feed(cat, fish);
    }
}

🍎 我们重点关注 Master 类中的这段代码:

public void feed(Animal animal, Food food){
	System.out.println("主人 " + name + " 给 " + animal.getName() + " 吃 " + food.getName());
}

❤️ 在这里我们 把参数列表设置成了父类类型,当使用时其实参可以为子类类型,Animal animal 可以传入一个 Dog类的参数(Dog为Animal的子类),而方法根据动态绑定机制属性看编译类型,方法看运行类型)判断这个是属于何种运行类型,比如 Dog类,则在方法中调用 Dog类的方法的 getName()(没有则在父类中查找),这便是一种多态参数的体现。

❤️ 在实际应用中,我们常常 在方法体里进行对象类型的判断,比如,在 feed方法中,我们可以判断 animal 到底是什么类型,如果是 Dog类型,则向下转型,调用相应的方法,比如发出 “汪汪汪~”的声音,以此类推。

🍌 实现结果:

java实现多对象数组 java多态数组_System_06