【java面向对象进阶】------多态综合案例
0.需求描述
定义狗类
-
属性:
- 年龄
- 颜色
-
行为:
eat(String something)方法(something 表示吃的东西)- 看家
lookHome方法(无参数)
定义猫类
-
属性:
- 年龄
- 颜色
-
行为:
eat(String something)方法(something 表示吃的东西)- 逮老鼠
catchMouse方法(无参数)
定义 Person 类 / 饲养员
-
属性:
- 姓名
- 年龄
-
行为:
-
keepPet(Dog dog, String something)方法- 功能:喂养宠物狗,something 表示喂养的东西
-
keepPet(Cat cat, String something)方法- 功能:喂养宠物猫,something 表示喂养的东西
-
-
其他要求:
- 生成空参有参构造
- set 和 get 方法
定义测试类(完成以下打印效果):
-
keepPet(Dog dog, String something)方法打印内容如下:年龄为30岁的老王养了一只黑颜色的2岁的狗 2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃 -
keepPet(Cat cat, String something)方法打印内容如下:年龄为25岁的老李养了一只灰颜色的3岁的猫 3岁的灰颜色的猫眯着眼睛侧着头吃鱼
思考:
-
Dog 和 Cat 都是 Animal 的子类,以上案例中针对不同的动物,定义了不同的
keepPet方法,过于繁琐,能否简化?并体会简化后的好处? -
Dog 和 Cat 虽然都是 Animal 的子类,但是都有其特有方法,能否想办法在
keepPet中调用特有方法?
需求分析见下图:

1. 项目结构(包:demo3)

demo3/
├── Animal.java // 动物基类
├── Dog.java // 狗类(继承 Animal)
├── Cat.java // 猫类(继承 Animal)
├── Person.java // 人类(使用 Animal 多态)
└── Test.java // 测试入口
关键设计:
Person的keepPet方法参数是Animal,却能喂狗、喂猫 —— 这就是多态的力量!
2. 完整代码
2.1 Animal.java —— 动物基类
package demo3;public class Animal {private int age;private String color;// 无参构造public Animal() {}// 有参构造public Animal(int age, String color) {this.age = age;this.color = color;}// getter 和 setterpublic int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}// 默认的 eat 方法(子类可选择重写)public void eat(String something) {System.out.println("动物在吃" + something);}
}
虽然
Animal不是抽象类,但它提供了通用行为。子类通过@Override提供个性化实现。
2.2 Dog.java —— 狗类
package demo3;public class Dog extends Animal {// 无参构造public Dog() {}// 有参构造,调用父类构造器public Dog(int age, String color) {super(age, color);}// 重写父类的 eat 方法,体现狗的吃法@Overridepublic void eat(String something){System.out.println(getAge() + "岁的" + getColor() + "颜色的狗两只前腿死死的抱住" + something + "猛吃");}// 狗特有的行为public void lookHome(){System.out.println("狗在看家");}
}
2.3 Cat.java —— 猫类
package demo3;public class Cat extends Animal {// 无参构造public Cat() {}// 有参构造,调用父类构造器public Cat(int age, String color) {super(age, color);}// 重写父类的 eat 方法,体现猫的吃法@Overridepublic void eat(String something){System.out.println(getAge() + "岁的" + getColor() + "颜色的猫眯着眼睛侧着头吃" + something);}// 猫特有的行为public void catchMouse(){System.out.println("猫在抓老鼠");}
}
多态体现:
Dog和Cat对eat()有不同的实现,但对外都遵循Animal的接口契约。
2.4 Person.java —— 人类(多态使用者)
package demo3;public class Person {private int age;private String name;// 无参构造public Person() {}// 有参构造public Person(int age, String name) {this.age = age;this.name = name;}// getter 和 setterpublic int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}// 核心方法:使用多态接收 Animal 类型的宠物public void keepPet(Animal pet, String somthing){// 使用 instanceof 判断具体类型(Java 17+ 模式匹配)if(pet instanceof Dog d){System.out.println(age + "岁的" + name + "养了一只" + pet.getColor() + "颜色的" + pet.getAge() + "岁的狗");d.eat(somthing); // 调用 Dog 的 eat}else if(pet instanceof Cat c){System.out.println(age + "岁的" + name + "养了一只" + pet.getColor() + "颜色的" + pet.getAge() + "岁的猫");c.eat(somthing); // 调用 Cat 的 eat}else{System.out.println("没有这种动物");}}
}
多态关键点:
- 方法参数是
Animal(父类),但实际传入的是Dog或Cat(子类);- 通过
instanceof获取具体类型后,调用其重写的eat()方法;- 即使去掉
instanceof,直接写pet.eat(somthing),也能正确执行子类逻辑(这才是纯多态)。
2.5 Test.java —— 测试类
package demo3;public class Test {public static void main(String[] args) {// 创建人:张三Person p1 = new Person(30, "张三");// 创建狗(向上转型:Animal 引用指向 Dog 对象)Animal pet1 = new Dog(2, "黑");p1.keepPet(pet1, "骨头");System.out.println();// 创建人:老李Person p2 = new Person(25, "老李");// 创建猫(向上转型)Animal pet2 = new Cat(3, "灰");p2.keepPet(pet2, "鱼");}
}
输出结果:
2.6 多态原理总结
| 概念 | 说明 |
|---|---|
| 向上转型 | Animal pet = new Dog(...); —— 父类引用指向子类对象 |
| 方法重写 | Dog 和 Cat 重写了 eat(),提供不同行为 |
| 动态绑定 | JVM 在运行时根据对象实际类型决定调用哪个 eat() |
| instanceof | 用于类型检查(本例用于个性化输出,非必须) |
多态的本质:
编译时看引用类型(Animal),运行时看实际对象类型(Dog/Cat)。

