文章目录
一、学生喂养三种宠物:猫、狗和鸟
- 动物类(Animal):属性(name,age)方法(speak、move、eat)
- 猫类(Cat):继承动物类,添加新方法(play)
- 狗类(Dog): 继承动物类,添加新方法(play)
- 鸟类(Bird):继承动物类,添加新方法(play)
- 学生类(Student):属性(name)方法(feed(animal))
(一)编程实现
1、创建动物类
package p03.t03;
/**
* 功能;动物类
* 作者:刘金花
* 日期:2022 年05月12日
*/
public class Animal {
private String name;
private int 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 void speak() {
System.out.println(name + "今年" + age + "岁了。");
}
public void move() {
System.out.println(name + "在动......");
}
public void eat() {
System.out.println(name + "在吃......");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2、继承动物类,创建猫类
package p03.t03;
/**
* 功能;猫类
* 作者:刘金花
* 日期:2022 年05月12日
*/
public class Cat extends Animal {
/**
* 子类改写父类的同名同参方法(纵向多态)
*/
@Override
public void move() {
System.out.println("猫咪[" + getName() +"]在爬树。");
}
/**
* 子类改写父类的同名同参方法(纵向多态)
*/
@Override
public void eat() {
System.out.println("猫咪[" + getName() + "]爱吃鱼虾。");
}
/**
* 子类添加新的方法
*/
public void play() {
System.out.println("猫咪[" + getName() + "]玩老鼠。");
}
}
3、继承动物类,创建狗类
package p03.t03;
/**
* 功能;狗类
* 作者:刘金花
* 日期:2022 年05月12日
*/
public class Dog extends Animal {
/**
* 子类改写父类的同名同参方法(纵向多态)
*/
@Override
public void move() {
System.out.println("狗崽[" + getName() +"]在走路。");
}
/**
* 子类改写父类的同名同参方法(纵向多态)
*/
@Override
public void eat() {
System.out.println("狗崽[" + getName() + "]爱啃骨头。");
}
/**
* 子类添加新的方法
*/
public void play() {
System.out.println("狗崽[" + getName() + "]玩树枝。");
}
}
4、继承动物类,创建鸟类
package p03.t03;
/**
-
功能;鸟类
-
作者:刘金花
-
日期:2022 年05月12日
/
public class Bird extends Animal{
/*- 子类改写父类的同名同参方法(纵向多态)
*/
@Override
public void move() {
System.out.println(“麻雀子[” + getName() +“]在找大虫子。”);
}
/**
- 子类改写父类的同名同参方法(纵向多态)
*/
@Override
public void eat() {
System.out.println(“麻雀子[” + getName() + “]爱吃大虫子。”);
}/**
- 子类添加新的方法
*/
public void play() {
System.out.println(“麻雀子[” + getName() + “]在玩老鹰的羽毛。”);
}
}
- 子类改写父类的同名同参方法(纵向多态)
5、创建学生类
- 针对不同动物定义不同的喂养方法,这样就无法体现多态
- 应该定义一个喂养方法,传入的是动物对象,而不是具体的猫对象、狗对象或鸟对象。
- Student类的feed()方法,参数是Animal对象,可以指向狗、可以指向猫、可以指向鸟,然后调用animal.move()与animal.eat()时就会根据传入的不同动物而呈现不同的形态。Java提供了一个关键字
instanceof
,用来判断一个对象是否是某个类(或接口)的实例或者子类实例。
package p03.t03;
/**
* 功能;学生类
* 作者:刘金花
* 日期:2022 年05月12日
*/
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void feed(Animal animal) {
animal.move(); //体现多态(子类改写了父类的同名同参方法)
animal.eat(); // 体现多态(子类改写了父类的同名同参方法)
animal.speak(); // 子类完全继承了父类的方法
if (animal instanceof Cat) { // 判断是否是猫实例
System.out.println(name + "喂养猫咪[" + animal.getName() + "]。");
} else if (animal instanceof Dog) { // 判断是否是狗实例
System.out.println(name + "喂养狗崽[" + animal.getName() + "]。");
} else if (animal instanceof Bird) { //判断是否是鸟实例
System.out.println(name + "喂养麻雀子[" + animal.getName() + "]。");
} else {
System.out.println(name + "喂养动物[" + animal.getName() + "]。");
}
}
}
6、创建测试学生类 TestStudent类
- 代码如下:
package p03.t03;
/**
* 功能;测试学生类
* 作者:刘金花
* 日期:2022 年05月12日
*/
public class TestStudent {
public static void main(String[] args) {
// 创建学生对象
Student student = new Student();
student.setName("张三丰");
// 创建第一个动物
Animal animal1 = new Cat();
animal1.setName("白金");
animal1.setAge(3);
// 创建第二个动物
Animal animal2 = new Dog();
animal2.setName("胖墩");
animal2.setAge(2);
// 创建第三个动物
Animal animal3 = new Bird();
animal3.setName("飞飞");
animal3.setAge(2);
// 调用学生对象的喂养方法,传入不同的动物对象
student.feed(animal1);
student.feed(animal2);
student.feed(animal3);
}
}
7、运行程序,查看结果
-
运行
TestStudent类
-
在第十五行、第二十行与第二十五行分别创建猫、狗与鸟对象,注意指向的都是父类Animal变量animal1、animal2与animal3,传入学生对象的feed()方法,在feed()方法调用参数对象的move()与eat()方法时,程序在编译时自动识别具体的子类对象,从而选择性的调用对应的方法,这就是Java多态性的体现。由此可见,多态不仅解决了方法同名的问题,而且还使程序变得更加灵活,从而有效地提高程序的可扩展性和可维护性。
-
美中不足之处:运行结果当中没有显示出各种动物的玩法
-
修改Student类,直接添加一句
animal.play()
,但是要报错,怎么办呢?
-
此时,我们要利用对象的向下转型(downcasting)
-
再次运行测试学生类,查看结果
(二)知识点讲解
- 定义:在Java中,多态指不同类的对象再调用同一个在调用同一个方法时所呈现出的多种不同行为。
- 说明:通常来说,在一个类中定义的属性和方法被其他类继承或重写后,当把子类对象直接赋值给父类引用变量时,相同引用类型的变量调用同一个方法所呈现出的多种不同形态。
- 作用:通过多态,消除了类之间的耦合关系,大大提高了程序的可扩展性和可维护性。
- 注意:Java的多态性是由类的继承、方法重写以及父类引用指向子类对象体现的。由于一个父类可以有多个子类,多个子类都可以重写子类方法,并且多个不同的子类对象也可以指向同一个父类。这样,程序只有在运行时才能知道具体代表的是那个子类对象,这就体现了多态性。
(三)拓展练习
任务1、汽车接口、公共汽车类与载重卡车类
- 编写汽车接口
Vehicle
,有跑方法run()。编写公共汽车类Bus和载重卡车类Truck实现汽车接口,公共汽车类增加属性:最大载客量(maxCapacity
),增加报站方法(report(String station)
),重写跑方法。载重卡车类增加属性:最大载重量(maxLoad
),增加装货(load(String cargo, double weight)
)、卸货方法(unload(String cargo, double weight)
),重写跑方法。编写测试类测试2个类,使用汽车类引用公共汽车对象和载重汽车对象,让汽车跑起来.
任务2、驾驶员类、测试驾驶员类
- 编写驾驶员(Driver)类,声明属性:姓名。方法:驾驶(driver)方法,方法的参数是任务1的汽车接口,方法体中调用汽车接口的跑方法。测试类中调用驾驶员driver方法时参数传递汽车接口的子类对象,查看输出接口。
- 实现思路:把父接口作为方法的参数;将父接口的子类对象作为参数传入