狗类
猫类
饲养员
测试类
完成以下打印效果:
年龄为30岁的老王养了一只黑颜色的2岁的狗。
2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃。
年龄为25岁的老李养了一只灰颜色的3岁的猫。
3岁的灰颜色的猫眯着眼睛侧着头吃鱼。
思考
package com.app.demo24_polymorphic.been;
/**
* 动物类
*/
public class Animal {
/*
定义动物相同的属性:
年龄,颜色
*/
private int age;
private String color;
/*
提供无参数的构造器
提供有全部参数的构造器
*/
public Animal() {}
public Animal(int age, String color) {
this.age = age;
this.color = color;
}
/*
提供全套的get和set方法
方便暴露属性的取值和赋值
*/
public 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;
}
/*
定义动物相同的行为:
吃东西
*/
public void eat(String something) {
System.out.println("动物在吃" + something);
}
}
package com.app.demo24_polymorphic.been;
/**
* 狗类:继承父类动物类
*/
public class Dog extends Animal{
/*
由于狗类继承了父类动物类,
因此只需要在狗类中定义狗特有的行为就好了
定义狗特有的行为:看门
*/
public void lookHome() {
System.out.println("狗正趴在门口~");
}
/*
提供无参数的构造器
提供有参数的构造器
*/
public Dog() {}
public Dog(int age, String color) {
super(age, color);
}
/*
由于父类动物类中的吃东西的行为是面向所有动物的,
又因为需求中有对狗吃东西的描述:2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃。
因此需要重写父类的eat方法。
*/
@Override
public void eat(String something) {
System.out.println(getAge() + "岁的" + getColor() + "颜色的狗两只前腿死死的抱住" + something + "猛吃。");
}
}
package com.app.demo24_polymorphic.been;
/**
* 猫类:继承动物类
*/
public class Cat extends Animal{
/*
由于猫类继承了父类动物类,
因此只需要在猫类中定义猫特有的行为就好了
定义猫特有的行为:逮老鼠
*/
public void catchMouse() {
System.out.println("猫正在奋力的逮老鼠~~");
}
/*
提供无参数的构造器
提供有参数的构造器
*/
public Cat() {}
public Cat(int age, String color) {
super(age, color);
}
/*
由于父类动物类中的吃东西的行为是面向所有动物的,
又因为需求中有对猫吃东西的描述:3岁的灰颜色的猫眯着眼睛侧着头吃鱼
因此需要重写父类的eat方法。
*/
@Override
public void eat(String something) {
System.out.println(getAge() + "岁的" + getColor() + "颜色的猫眯着眼睛侧着头吃" + something + "。");
}
}
package com.app.demo24_polymorphic.been;
/**
* 饲养员类
*/
public class Person {
/*
定义饲养员的属性:
姓名、年龄
*/
private String name;
private int age;
/*
提供无参数的构造器
提供有全部参数的构造器
*/
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/*
提供全套的get和set方法
方便暴露其属性的取值和赋值
*/
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 keepPet(Dog dog, String something) {
System.out.println("年龄为" + age + "岁的" + name + "养了一只" + dog.getColor() + "颜色的" + dog.getAge() + "岁的狗");
// 狗吃饲养员喂养的食物
dog.eat(something);
}*/
/*
未使用多态前:
定义饲养员喂养宠物猫的行为
参数一:猫对象;参数二:喂养的食物
*/
public void keepPet(Cat cat, String something) {
System.out.println("年龄为" + age + "岁的" + name + "养了一只" + cat.getColor() + "颜色的" + cat.getAge() + "岁的猫");
// 猫吃饲养员喂养的食物
cat.eat(something);
}
/*
使用多态来定义饲养员喂养宠物狗、猫的行为
参数一:动物对象;参数二:喂养的食物
*/
public void keepPet(Animal a, String something) {
// 无法直接调用子类中的特有行为
// a.lookHome();
// a.catchMouse();
// 判断该动物对象类型是否为狗对象类型
/*if (a instanceof Dog) {
// 是,则将动物对象类型强转为狗对象类型
Dog d = (Dog) a;
System.out.println("年龄为" + age + "岁的" + name + "养了一只" + d.getColor() + "颜色的" + d.getAge() + "岁的狗");
// 狗吃饲养员喂养的食物
d.eat(something);
// 可以调用子类中的特有行为
// d.lookHome();
} else if (a instanceof Cat) { // 否,则判断该动物对象类型是否为猫对象类型
// 是,则将动物对象类型强转为猫对象类型
Cat c = (Cat) a;
System.out.println("年龄为" + age + "岁的" + name + "养了一只" + c.getColor() + "颜色的" + c.getAge() + "岁的猫");
// 猫吃饲养员喂养的食物
c.eat(something);
// 可以调用子类中的特有行为
// c.catchMouse();
} else { // 否,则说明没有这种动物
System.out.println("没有这种动物喔!");
}*/
/*
优化写法
*/
// 判断该动物对象类型是否为狗对象类型
if (a instanceof Dog d) { // 是,则将动物对象类型强转为狗对象类型
System.out.println("年龄为" + age + "岁的" + name + "养了一只" + d.getColor() + "颜色的" + d.getAge() + "岁的狗");
// 狗吃饲养员喂养的食物
d.eat(something);
} else if (a instanceof Cat c) { // 否,则判断该动物对象类型是否为猫对象类型:是,则将动物对象类型强转为猫对象类型
System.out.println("年龄为" + age + "岁的" + name + "养了一只" + c.getColor() + "颜色的" + c.getAge() + "岁的猫");
// 猫吃饲养员喂养的食物
c.eat(something);
} else { // 否,则说明没有这种动物
System.out.println("没有这种动物喔!");
}
}
}
package com.app.demo24_polymorphic.test;
import com.app.demo24_polymorphic.been.Animal;
import com.app.demo24_polymorphic.been.Cat;
import com.app.demo24_polymorphic.been.Dog;
import com.app.demo24_polymorphic.been.Person;
/**
* 测试类
* 完成以下打印效果:
* 年龄为30岁的老王养了一只黑颜色的2岁的狗。
* 2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃。
* 年龄为25岁的老李养了一只灰颜色的3岁的猫。
* 3岁的灰颜色的猫眯着眼睛侧着头吃鱼。
*/
public class Test {
public static void main(String[] args) {
/*// 创建饲养员1
Person p1 = new Person("老王", 30);
// 未使用多态前:创建宠物狗
Dog dog = new Dog(2, "黑");
// 饲养员1调用喂养宠物狗的行为方法,完成喂养
p1.keepPet(dog, "骨头");
// 创建饲养员2
Person p2 = new Person("老李", 25);
// 未使用多态前:创建宠物猫
Cat cat = new Cat(3, "灰");
// 饲养员2调用喂养宠物猫的行为方法,完成喂养
p2.keepPet(cat, "鱼");*/
Person p1 = new Person("老王", 30);
// 使用多态:创建宠物狗
Animal dog = new Dog(2, "黑");
p1.keepPet(dog, "骨头");
Person p2 = new Person("老李", 25);
// 使用多态:创建宠物猫
Animal cat = new Cat(3, "灰");
p2.keepPet(cat, "鱼");
}
}
年龄为30岁的老王养了一只黑颜色的2岁的狗
2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃。
年龄为25岁的老李养了一只灰颜色的3岁的猫
3岁的灰颜色的猫眯着眼睛侧着头吃鱼。
Process finished with exit code 0
可以从以上需求看出:
分析结构图:
人类(顶层父类)
package com.app.demo25_interface_abstract.been;
/**
* 人类:顶层父类
* 注意:
* 1、人类是顶层父类,主要作用就是定义所有子类的共同属性、行为,这样子类就不需要重复定义。
* 2、因此构造对象的时候,也是构造子类的对象,如果直接构造顶层父类:人类的对象,此时是没有意义的。
* 3、所以,顶层父类是定义为抽象类的:目的就是为了不让外界直接创建顶层父类的对象。
*/
public abstract class Person {
/*
定义子类的共同属性:
姓名、年龄
*/
private String name;
private int age;
/*
提供无参数的构造器
提供带全部参数的构造器
*/
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/*
提供全套的get和set方法,
方便合理暴露其属性的取值和赋值
*/
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; }
}
运动员类(人类的子类,所有运动员的父类)
package com.app.demo25_interface_abstract.been;
/**
* 运动员类
* 必须定义为抽象类:
* 1、因为运动员的学习行为方法是定义为抽象方法
* 2、因为每个运动员要学习的内容不一样,因此需要定义为抽象方法,让子类必须重写运动员类(父类)的学习方法
*/
public abstract class Sportsman extends Person{
/*
提供无参数的构造器
提供带全部参数的构造器
*/
public Sportsman() {}
public Sportsman(String name, int age) {
// super(): 将构造运动员对象的属性传递给父类(顶层父类:人类)
super(name, age);
}
/*
定义运动员的共同行为:学习
必须定义为抽象方法,让每个运动员自己实现。
因为每个运动员要学习的内容都不一样。
*/
public abstract void study(String name);
}
教练类(人类的子类,所有教练的父类)
package com.app.demo25_interface_abstract.been;
/**
* 教练类
* 必须定义为抽象类:
* 1、因为教练的教学行为方法是定义为抽象方法
* 2、因为每个教练要教学的内容不一样,因此需要定义为抽象方法,让子类必须重写教练类(父类)的教学方法
*/
public abstract class Coach extends Person{
/*
提供无参数的构造器
提供带全部参数的构造器
*/
public Coach() {}
public Coach(String name, int age) {
// super(): 将构造教练对象的属性传递给父类(顶层父类:人类)
super(name, age);
}
/*
定义教练的共同行为:教学
必须定义为抽象方法,让每个教练自己实现。
因为每个教练要教学的内容都不一样。
*/
public abstract void teach(String name);
}
英语接口(乒乓球相关的需要实现说英语方法)
package com.app.demo25_interface_abstract.been;
/**
* 定义英语接口:乒乓球运动员、教练都要说英语
*/
public interface English {
/*
定义说英语的抽象方法:
1、接口中的方法,默认是公开、抽象的
2、因此实现接口时,必须重写该方法
3、所以修饰符:public、abstract也可以省略不写!
*/
void speakEnglish(String name);
}
乒乓球运动员类(运动员的子类,英语接口的实现类)
package com.app.demo25_interface_abstract.been;
/**
* 乒乓球运动员类
* 1、需要继承运动员类:Sportsman
* 2、需要实现英语接口:English
* 3、因此必须重写运动类、英语接口的方法
*/
public class PingPongSportsman extends Sportsman implements English{
/*
提供无参数的构造器
提供带全部参数的构造器
*/
public PingPongSportsman() {}
public PingPongSportsman(String name, int age) {
// super(): 将构造乒乓球运动员对象的属性传递给运动员类(父类)
super(name, age);
}
// 1、重写父类的学习方法
@Override
public void study(String name) {
System.out.println("乒乓球运动员" + name + "正在学习如何打乒乓球~~");
}
// 2、重写英语接口的说英语方法
@Override
public void speakEnglish(String name) {
System.out.println("乒乓球运动员" + name + "正在说着一口流利的英语 ~^_^~");
}
}
乒乓球教练(教练的子类,英语接口的实现类)
package com.app.demo25_interface_abstract.been;
/**
* 乒乓球教练类
* 1、需要继承教练类:Coach
* 2、需要实现英语接口:English
* 3、因此必须重写教练类、英语接口的方法
*/
public class PingPongCoach extends Coach implements English{
/*
提供无参数的构造器
提供带全部参数的构造器
*/
public PingPongCoach() {}
public PingPongCoach(String name, int age) {
// super(): 将构造器乒乓球教练对象的属性传递给教练类(父类)
super(name, age);
}
// 1、重写父类的教学方法
@Override
public void teach(String name) {
System.out.println("乒乓球教练" + name + "正在向学员们传授最正宗的乒乓球打法~~");
}
// 2、重写英语接口的说英语方法
@Override
public void speakEnglish(String name) {
System.out.println("乒乓球教练" + name + "正在飙着一口流利的英语 @^_^@");
}
}
篮球运动员类(运动员的子类)
package com.app.demo25_interface_abstract.been;
/**
* 篮球运动员类
* 1、需要继承运动员类:Sportsman
* 2、因此必须重写运动类的方法
*/
public class BasketballSportsman extends Sportsman{
/*
提供无参数的构造器
提供带全部参数的构造器
*/
public BasketballSportsman() {}
public BasketballSportsman(String name, int age) {
// super(): 将构造器篮球运动员对象的属性传递给运动员类(父类)
super(name, age);
}
// 1、重写父类的学习方法
@Override
public void study(String name) {
System.out.println("篮球运动员" + name + "正在学习如何打篮球~~");
}
}
篮球教练类(教练的子类)
package com.app.demo25_interface_abstract.been;
/**
* 篮球教练类
* 1、需要继承教练类:Coach
* 2、因此必须重写教练类的方法
*/
public class BasketballCoach extends Coach{
/*
提供无参数的构造器
提供带全部参数的构造器
*/
public BasketballCoach() {}
public BasketballCoach(String name, int age) {
// super(): 将构造篮球教练对象的属性传递给教练类(父类)
super(name, age);
}
// 1、重写父类的教学方法
@Override
public void teach(String name) {
System.out.println("篮球教练" + name + "正在向学员们传授最正宗的篮球技术~~");
}
}
测试类:
package com.app.demo25_interface_abstract.test;
import com.app.demo25_interface_abstract.been.*;
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
// 创建乒乓球教练对象
PingPongCoach ppc = new PingPongCoach("张飞", 66);
// 乒乓球教练开始教学
ppc.teach(ppc.getName());
// 乒乓球教练开始飙英语
ppc.speakEnglish(ppc.getName());
System.out.println();
// 创建乒乓球运动员对象
PingPongSportsman pps = new PingPongSportsman("甄姬", 23);
// 乒乓球运动员开始学习
pps.study(pps.getName());
// 乒乓球运动员开始说英语
pps.speakEnglish(pps.getName());
System.out.println("------------------------");
// 创建篮球教练对象
BasketballCoach bbc = new BasketballCoach("赵云", 65);
// 篮球教练开始教学
bbc.teach(bbc.getName());
System.out.println();
// 创建篮球运动员对象
BasketballSportsman bbs = new BasketballSportsman("蔡徐坤", 25);
// 篮球运动员开始学习
bbs.study(bbs.getName());
}
}
乒乓球教练张飞正在向学员们传授最正宗的乒乓球打法~~
乒乓球教练张飞正在飙着一口流利的英语 @^_^@
乒乓球运动员甄姬正在学习如何打乒乓球~~
乒乓球运动员甄姬正在说着一口流利的英语 ~^_^~
------------------------
篮球教练赵云正在向学员们传授最正宗的篮球技术~~
篮球运动员蔡徐坤正在学习如何打篮球~~
Process finished with exit code 0