首页 > 分享 > 15

15

多态的综合练习

1、需求

狗类

属性:年龄,颜色行为: eat(String something):表示吃东西lookHome():看家

猫类

属性:年龄,颜色行为: eat(String something):吃东西catchMouse():逮老鼠

饲养员

属性:姓名,年龄行为: keepPet(Dog dog, String something):喂养宠物狗,something表示喂养的东西keepPet(Cat cat, String something):喂养宠物猫,something表示喂养的东西需要无参与有参构造器,set和get方法

测试类

完成以下打印效果:

年龄为30岁的老王养了一只黑颜色的2岁的狗。

2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃。

年龄为25岁的老李养了一只灰颜色的3岁的猫。

3岁的灰颜色的猫眯着眼睛侧着头吃鱼。

思考

1、Dog和Cat都是Animal的子类,以上案例中针对不同的动物,定义了不同的keepPet方法,过于繁琐,能否简化,并体会简化后的好处2、Dog和Cat虽然都是Animal的子类,但是都有其特有方法,能否想办法在keepPet中调用特有方法? 2、分析 我们可以发现这个需求中: 猫、狗都属于动物,属性也一样,也有相同的行为;因此我们需要让猫和狗类继承动物类,抽离相同的属性、行为定义在动物类中;猫和狗类只需要定义它们自己特有的方法即可。饲养员类要单独定义。 提问? 为啥人不继承动物类呢?人也是动物啊?这个问题没毛病,但是不符合我们的这个需求!我们的需求是人饲养宠物猫、宠物狗,而不是人饲养人。 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); } }

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950

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 + "猛吃。"); } }

12345678910111213141516171819202122232425262728293031323334

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 + "。"); } }

12345678910111213141516171819202122232425262728293031323334

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("没有这种动物喔!"); } } }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117

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, "鱼"); } }

123456789101112131415161718192021222324252627282930313233343536373839404142

年龄为30岁的老王养了一只黑颜色的2岁的狗 2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃。 年龄为25岁的老李养了一只灰颜色的3岁的猫 3岁的灰颜色的猫眯着眼睛侧着头吃鱼。 Process finished with exit code 0 1234567

接口和抽象类的综合案例

1、需求 编写带有接口和抽象类的标准Javabean类: 我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。请用所有知识分析,在这个案例中,哪些是具体类,哪些是抽象类,哪些是接口? 乒乓球运动员:姓名、年龄、学打乒乓球,说英语。篮球运动员:姓名、年龄、学打篮球。乒乓球教练:姓名、年龄、教打乒乓球,说英语。篮球教练:姓名、年龄、教打篮球。 2、分析

可以从以上需求看出:

他们都有共同的属性,因此可以定义一个人的类,来定义这些共同的属性,让他们继承乒乓球运动员和乒乓球教练都有说英语的共同行为,因此需要定义一个说英语的接口,让他们实现运动员都有一个共同的行为,那就是学习打球,但是由于球类不同,因此这个学习方法是抽象的,必须让运动员自己实现。教练都有一个共同的行为,那就是教学生打球,但是由于球类不同,因此这个教学方法是抽象的,必须让教练自己实现。最后要注意一个细节: 由于人类是运动员和教练的顶级父类,因此必须是抽象的。因为此时不能让外界直接创建顶层父类人的对象,此时是没有意义的。

分析结构图

在这里插入图片描述

3、实现

人类(顶层父类)

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

12345678910111213141516171819202122232425262728293031323334353637

运动员类(人类的子类,所有运动员的父类)

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

1234567891011121314151617181920212223242526

教练类(人类的子类,所有教练的父类)

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

1234567891011121314151617181920212223242526

英语接口(乒乓球相关的需要实现说英语方法)

package com.app.demo25_interface_abstract.been; /** * 定义英语接口:乒乓球运动员、教练都要说英语 */ public interface English { /* 定义说英语的抽象方法: 1、接口中的方法,默认是公开、抽象的 2、因此实现接口时,必须重写该方法 3、所以修饰符:public、abstract也可以省略不写! */ void speakEnglish(String name); } 1234567891011121314

乒乓球运动员类(运动员的子类,英语接口的实现类)

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 + "正在说着一口流利的英语 ~^_^~"); } }

12345678910111213141516171819202122232425262728293031

乒乓球教练(教练的子类,英语接口的实现类)

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 + "正在飙着一口流利的英语 @^_^@"); } }

12345678910111213141516171819202122232425262728293031

篮球运动员类(运动员的子类)

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 + "正在学习如何打篮球~~"); } }

123456789101112131415161718192021222324

篮球教练类(教练的子类)

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 + "正在向学员们传授最正宗的篮球技术~~"); } }

123456789101112131415161718192021222324

测试类

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

1234567891011121314151617181920212223242526272829303132333435363738394041 4、运行结果

乒乓球教练张飞正在向学员们传授最正宗的乒乓球打法~~ 乒乓球教练张飞正在飙着一口流利的英语 @^_^@ 乒乓球运动员甄姬正在学习如何打乒乓球~~ 乒乓球运动员甄姬正在说着一口流利的英语 ~^_^~ ------------------------ 篮球教练赵云正在向学员们传授最正宗的篮球技术~~ 篮球运动员蔡徐坤正在学习如何打篮球~~ Process finished with exit code 0 123456789101112

相关知识

2月15
宠物医生专业培训不足15%
15 种长毛犬(照片)
狗狗训练:[15]牛头梗握手
2024韩国宠物展览会3月15
[橘圆猫] 猫咪行为学进阶篇[15]
《梦想海贼王》卡15小技巧
抽检40批次,15批次产品发现问题
店主网售带病宠物被判赔15万元
龙斗士战宠15星技能大全

网址: 15 https://m.mcbbbk.com/newsview280751.html

所属分类:萌宠日常
上一篇: 宠物犬训练的基本原则
下一篇: 魔兽宠物天赋怎么改【吧友互助吧】