主讲人:王少华 QQ群号:483773664
一、 子类到父类的转换(向上转型)
(一) 基本数据之间的类型转换
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(Dogdog)和feed(Penguin penguin)方法,增加唯一的feed(Pet pet)方法,如下所示
publicclass Master {
private String name = "";// 主人名字
privateintmoney = 0; //元宝数
/**
* 有参构造方法。
*
* @param name
* 主人名字
* @param money
* 元宝数
*/
public Master(String name, int money) {
this.name = name;
this.money = money;
}
publicvoid setName(String name) {
this.name = name;
}
publicvoid setMoney(int money) {
this.money = money;
}
publicint getMoney() {
returnmoney;
}
public String getName() {
returnname;
}
/**
* 主人给宠物喂食。
*/
publicvoid feed(Pet pet) {
pet.eat();
}
}
2. Test:测试类
publicclass Test {
publicstaticvoid 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);// 主人给企鹅喂食
}
}
备注:
- 向上转型的规则:通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法;
- 使用多态的好处:减少代码量,提高代码的可扩展性。
-
验证:多态的扩展性
增加宠物Cat类,继承Pet类并重写eat()y方法
publicclass Cat extends Pet{
private String color;//颜色
public Cat(String name, String color) {
super(name);
this.color = color;
}
publicvoid setColor(String color) {
this.color = color;
}
public String getColor() {
returncolor;
}
/**
* 实现吃饭方法
*/
publicvoid eat() {
if(getHealth()>=100){
System.out.println("狗狗"+this.getName() +"吃饱了,不需要喂食了!");
}else{
this.setHealth(this.getHealth()+4);
System.out.println("猫咪"+this.getName() + "吃饱啦!体力增加4。");
}
}
}
4. Test:添加领养和喂食猫的语句
publicclass Test {
publicstaticvoid main(String[] args) {
Dog dog = new Dog("欧欧", "雪娜瑞");
Penguin pgn = new Penguin("楠楠", "Q妹");
Cat cat = newCat("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. 需求:
假设主要可以同时给狗和企鹅喂食,但只能和狗玩飞盘游戏,只能和企鹅玩游泳游戏。
- 给Penguin类添加swim方法
-
实现:
给Dog类添加catchingFlyDisc()
publicvoid catchingFlyDisc(){
if(super.getLove()>=100){
super.setLove(100);
}else {
super.setLove(super.getLove()+10);
}
}
在测试类中,通过Pet调用Dog类中的cathingFlyDisc
3. 原因及结论
因为主人类只晓得它是一个宠物,而不知道它是狗还是企鹅,所以主人不知道应该跟这个宠物玩什么游戏。因此,在多态中,通过父类引用变量无法调用子类特有的方法
三、 使用父类作为方法返回值
使用父类作为方法的返回值,是Java中实现和使用多态的另一种方式。
(一) 需求
以使用父类作为方法返回值的方式,来实现主人领养宠物的功能
- 给Master类添加getPet(String typeId)方法,实现领养功能
- 创建测试类,根据主人选择宠物的类型编号来领养宠物
- 调用给宠物喂食,测试是否正确领养
-
实现
-
Master
修改Master类添加getPet(StringtypeId)方法,以父类Pet作为方法返回值。
/**
* 主人领养宠物
* @param typeId 宠物编号
* @return
*/
public Pet getPet(int typeId){
Pet pet=null;
if(typeId==1){
pet= new Dog("欧欧", "雪娜瑞");
}elseif(typeId==2){
pet = newPenguin("楠楠", "Q妹");
}
returnpet;
}
2. Test
在Test类中,添加领养信息
publicclass Test {
publicstaticvoid 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个条件
- 继承的存在,继承是多态的基础,没有继承就没有多态
- 子类重写父类方法,多态下调用子类重写后的方法
- 父类引用变量指向子类对象,子类到父类的类型转换
-
多态中的方法
- 通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法
- 通过父类引用变量无法调用子类特有的方法