什么是多态
主讲人:王少华 QQ群号:483773664
学习目标:
1)父类与子类间转换:向上转型
2)使用父类作为方法形参实现多态
3)使用父类作为返回值实现多态
一、子类到父类的转换(向上转型)
(一)基本数据之间的类型转换
1.自动进行类型转换
//将int型常量或变量的值赋给double型变量,可以自动进行类型转换
int i = 5;
double dl = i;
2.强制类型的转换
类型转换运算符是小括号,类型转换运算符的用法是
(type)variable
//将double型常量或变量的值赋给int型变量,进行强制类型转换
double d2 = 3.14;
int a = (int)
d2;
3.基本数据类型转换注意事项
基本类型之间的转换只能在数值类型之间进行,这里所说的数值类型包括:整数型、字符型和浮点型。但数值类型和布尔类型之间不能进行类型转换。
(二)引用数据类型转型
数据类型转换不但存在于基本数据类型之间,还存在于引用类型之间,但引用数据类型转型存在一些规则
1.引用类型之间的转换只能在具有继承关系的两个类这间进行。
Person person
= new Dog(); //Error
2.将一个父类引用指向一个子类对象,称为向转型(upcasting),自动进行类型转换。
Pet pet
= new Dog();
二、使用父类作为方法形参
用父类作为方法的形参,是Java中实现和使用多态的主要方式之一。
(一)解决给宠物喂食的难题
1.Master
修改Master类,注释feed(Dog dog)和feed(Penguin
penguin)方法,增加唯一的feed(Pet pet)方法,如下所示
public class Master {
private String name = "";//
主人名字
private int money = 0; //
元宝数
/**
* 有参构造方法。
*
* @param name
*主人名字
* @param money
*元宝数
*/
public Master(String name, int money) {
this.name = name;
this.money = money;
}
public void setName(String name)
{
this.name = name;
}
public void setMoney(int money) {
this.money = money;
}
public int getMoney() {
return money;
}
public String getName() {
return name;
}
/**
* 主人给宠物喂食。
*/
public void feed(Pet pet) {
pet.eat();
}
}
2.Test:测试类
public class Test {
public static void main(String[] args) {
Dog dog = new Dog("欧欧", "雪娜瑞");
Penguin pgn = new Penguin("楠楠", "Q妹");
dog.setHealth(80); // 设置健康值,以便正常喂食
pgn.setHealth(80); // 设置健康值,以便正常喂食
Master master = new Master("王先生", 100);
master.feed(dog);// 主人给狗狗喂食
master.feed(pgn);// 主人给企鹅喂食
}
}
备注:
1)向上转型的规则:通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法;
2)使用多态的好处:减少代码量,提高代码的可扩展性。
3.验证:多态的扩展性
增加宠物Cat类,继承Pet类并重写eat()y方法
public class Cat extends Pet{
private String color;//颜色
public Cat(String name, String color) {
super(name);
this.color = color;
}
public void setColor(String
color) {
this.color = color;
}
public String getColor() {
return color;
}
/**
* 实现吃饭方法
*/
public void eat() {
if(getHealth()>=100){
System.out.println("狗狗"+this.getName() +"吃饱了,不需要喂食了!");
}else{
this.setHealth(this.getHealth()+4);
System.out.println("猫咪"+this.getName() + "吃饱啦!体力增加4。");
}
}
}
4.Test:添加领养和喂食猫的语句
public class Test {
public static void main(String[] args) {
Dog dog = new Dog("欧欧", "雪娜瑞");
Penguin pgn = new Penguin("楠楠", "Q妹");
Cat cat = new
Cat("Tomcat", "黄色");
dog.setHealth(80); // 设置健康值,以便正常喂食
pgn.setHealth(80); // 设置健康值,以便正常喂食
cat.setHealth(80); //
设置健康值,以便正常喂食
Master master = new Master("王先生", 100);
master.feed(dog);// 主人给狗狗喂食
master.feed(pgn);// 主人给企鹅喂食
master.feed(cat);//
主人给猫喂食
}
}
(二)父类调用子类特有方法
1.需求:
假设主要可以同时给狗和企鹅喂食,但只能和狗玩飞盘游戏,只能和企鹅玩游泳游戏。
1)给Penguin类添加swim方法
2.实现:
给Dog类添加catchingFlyDisc()
public void catchingFlyDisc(){
if(super.getLove()>=100){
super.setLove(100);
}else {
super.setLove(super.getLove()+10);
}
}
在测试类中,通过Pet调用Dog类中的cathingFlyDisc
3.原因及结论
因为主人类只晓得它是一个宠物,而不知道它是狗还是企鹅,所以主人不知道应该跟这个宠物玩什么游戏。因此,在多态中,通过父类引用变量无法调用子类特有的方法
三、使用父类作为方法返回值
使用父类作为方法的返回值,是Java中实现和使用多态的另一种方式。
(一)需求
以使用父类作为方法返回值的方式,来实现主人领养宠物的功能
1)给Master类添加getPet(String typeId)方法,实现领养功能
2)创建测试类,根据主人选择宠物的类型编号来领养宠物
3)调用给宠物喂食,测试是否正确领养
(二)实现
1.Master
修改Master类添加getPet(String typeId)方法,以父类Pet作为方法返回值。
/**
* 主人领养宠物
* @param typeId 宠物编号
* @return
*/
public Pet getPet(int typeId){
Pet pet=null;
if(typeId==1){
pet= new Dog("欧欧", "雪娜瑞");
}elseif(typeId==2){
pet = new Penguin("楠楠", "Q妹");
}
return pet;
}
2.Test
在Test类中,添加领养信息
public class Test {
public static void main(String[] args) {
Master master = new Master("王先生", 100);
Scanner input = new Scanner(System.in);
System.out.println("欢迎您来到宠物店!");
System.out.print("请选择要领养的宠物类型:(1、狗狗 2、企鹅)");
int typeId = input.nextInt();
Pet pet = master.getPet(typeId);
if (pet != null) {
System.out.println("领养成功!");
pet.setHealth(80); //设置健康值,以便正常喂食
master.feed(pet);
} else {
System.out.println("对不起,没有此类型的宠物,领养失败");
}
}
}
四、总结
(一)实现多态的条件
通过以上示例对多态功能的详解,总结实现多态的3个条件
1)继承的存在,继承是多态的基础,没有继承就没有多态
2)子类重写父类方法,多态下调用子类重写后的方法;
3)父类引用变量指向子类对象,不能调用子类对象特有的方法
(二)多态中的方法
1)通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法
2)通过父类引用变量无法调用子类特有的方法