多态:多种形态
生活中的多态:同一个操作 因为环境不同 产生不同的效果
代码中的多态:同一个方法,因为实际参数或者返回值的不同,产生不同的效果
多态是面向对象三大特征之一,在实际开发中,多态随处可见,多态是提高代码质量重要的手段之一。
多态的表现形式:
1.父类作为形参,实参为子类类型
2.父类作为返回值,实际返回值为子类类型
2.1 父类作为形参
package com.qfedu.test3;
/**
* 狗类
* 属性
* 品种
* 行为:打印
* 无参构造
*
*/
public class Dog extends Pet{
private String strain;
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
public Dog() {}
public Dog(String name,int health,int love,String strain) {
super(name, health, love);
this.strain = strain;
}
@Override
public void print() {
super.print();
System.out.println("狗狗的品种是:" + strain);
}
public void toHospital() {
super.toHospital();
System.out.println("狗狗看病,吃药,吃骨头,健康值恢复!");
this.setHealth(100);
}
}
package com.qfedu.test3;
/**
* 企鹅类
* 属性:
* 性别
* 行为:打印方法 print()
* 无参构造
*
*/
public class Penguin extends Pet{
private String sex;
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Penguin() {}
public Penguin(String name,int health,int love,String sex) {
super(name, health, love);
this.sex = sex;
}
public void print() {
super.print();
System.out.println("企鹅的性别是" + sex);
}
public void toHospital() {
super.toHospital();
System.out.println("企鹅看病,打针,疗养,吃小鱼,健康值恢复!");
this.setHealth(100);
}
}
package com.qfedu.test3;
/**
* 企鹅类父类
* 共有的属性
* 名字
* 健康值
* 爱心值
* 行为
* 打印信息
* super访问父类的普通方法
*
*/
public class Pet {
private String name;
private int health;
private int love;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getLove() {
return love;
}
public void setLove(int love) {
this.love = love;
}
public Pet() {}
public Pet(String name,int health,int love) {
this.name = name;
this.health = health;
this.love = love;
}
public void toHospital() {
System.out.println("宠物看病");
}
void print() {
System.out.println("宠物的名字是:" + name + ",健康值是:" + health);
System.out.println("宠物的爱心值:" + love );
}
}
package com.qfedu.test3;
/**
* 主人类
* 属性:名字
* 行为:提供带宠物看病的方法
*
*/
public class Master {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void cureWithDog(Dog dog) {
if(dog.getHealth() < 60) {
dog.toHospital();
}else {
System.out.println("狗狗很健康,不需要看病!");
}
}
public void cureWithPenguin(Penguin penguin) {
if(penguin.getHealth() < 60) {
penguin.toHospital();
}else {
System.out.println("企鹅很健康,不需要看病!");
}
}
// 观察以上我们写的两个方法?有没有什么不太好的地方?
// 因为目前是按照一个宠物编写一个看病方法
// 这样的做法,以后随着系统的迭代更新,我们需要编写更多的方法
// 来应对系统中更多的宠物,这种写法不符合写代码的<开闭原则>
// 开闭原则:对扩展开放,对修改源代码关闭
// 所以:我们应该编写一个"万能"的方法,可以实现给所有的宠物看病
// Pet pet = new Dog();
public void cure(Pet pet) {
if(pet.getHealth() < 60) {
pet.toHospital();
}else {
System.out.println("宠物很健康,不需要看病!");
}
}
}
package com.qfedu.test3;
/**
* 使用多态之前的方式给宠物看病
*
*/
public class Test1 {
public static void main(String[] args) {
Master zhaosi = new Master();
zhaosi.setName("赵四");
Dog dog = new Dog("大黄", 55, 20, "大金毛");
zhaosi.cureWithDog(dog);
System.out.println(dog.getHealth());
Penguin p = new Penguin("大白", 20, 1, "雌");
zhaosi.cureWithPenguin(p);
System.out.println(p.getHealth());
}
}
package com.qfedu.test3;
/**
* 使用多态以后给宠物看病
*
*/
public class Test2 {
public static void main(String[] args) {
Master liuneng = new Master();
Dog dog = new Dog("大黄", 22, 10, "拉布拉多");
// 形参为父类 实参为子类 多态表现形式之一
// 继承的核心思想:子类是父类 子类与父类 是 is a 的关系
// 这里传入Dog类对象 是类型自动提升 子类自动提升为父类类型
// 多态向上转型,父类引用指向子类对象
// 此时可以调用的是子类重写父类的方法
// 以及继承自父类的方法
// 不能调用子类独有的方法
liuneng.cure(dog);
System.out.println(dog.getHealth());
Penguin p = new Penguin("小白", 12, 12, "雌性");
liuneng.cure(p);
System.out.println(p.getHealth());
}
}
2.2 父类作为返回值
package com.qfedu.test4;
public class Cat extends Pet{
private String furColor;
public String getFurColor() {
return furColor;
}
public void setFurColor(String furColor) {
this.furColor = furColor;
}
@Override
public void toHospital() {
super.toHospital();
System.out.println("猫咪看病,吃猫粮,打针,健康值恢复!");
setHealth(100);
}
}
package com.qfedu.test4;
/**
* 主人类
* 属性:名字
* 行为:抽奖送宠物 分别1234等奖 送不同的宠物
*
*/
public class Master {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 一等奖 送一只狗狗
* @return
*/
public Dog giveDog(){
Dog dog = new Dog("大黄", 100, 100, "金毛");
return dog;
}
/**
* 二等奖 送企鹅一只
* @return
*/
public Penguin givePenguin() {
Penguin p = new Penguin("大白", 100, 100, "雌");
return p;
}
/**
* 三等奖 送猫咪
* @return
*/
public Cat giveCat() {
Cat cat = new Cat();
cat.setName("花花");
cat.setLove(100);
cat.setHealth(100);
cat.setFurColor("绿色");
return cat;
}
/**
* 幸运奖 送成年东北虎一只
* @return
*/
public Tiger giveTiger() {
return new Tiger();
}
// 观察以上代码 我们发现 这种写法依然不符合开闭原则
// 如果有其他的奖项 我们还要继续编写代码 应对新的奖项
// 所以我们应该编写一个方法 用于实现所有的奖项
public Pet give(String condition){
if(condition.equals("一等奖")) {
Dog dog = new Dog("大黄", 100, 100, "金毛");
return dog;
}else if(condition.equals("二等奖")) {
Penguin p = new Penguin("大白", 100, 100, "雌");
return p;
}else if(condition.equals("三等奖")) {
Cat cat = new Cat();
cat.setName("花花");
cat.setLove(100);
cat.setHealth(100);
cat.setFurColor("绿色");
return cat;
}else if(condition.equals("幸运奖")) {
return new Tiger();
}else {
System.out.println("谢谢!");
return null;
}
}
}
package com.qfedu.test4;
public class Test1 {
public static void main(String[] args) {
Master zhaosi = new Master();
zhaosi.setName("赵四");
// 多态向上转型 父类引用指向子类对象
// 此时当前对象可以调用的是子类重写父类的方法
// 以及继承自父类的方法
// 不能调用子类独有的方法
Pet dog = zhaosi.give("一等奖");
dog.print();
Pet penguin = zhaosi.give("二等奖");
penguin.print();
}
}
3. 引用数据类型转换
自动提升
手动下降
3.1 向上转型
多态向上转型 父类引用指向子类对象
此时当前对象可以调用的是子类重写父类的方法
以及继承自父类的方法
不能调用子类独有的方法
<父类型> <引用变量名> = new <子类型>();
package com.qfedu.test4; public class Test1 { public static void main(String[] args) { Master zhaosi = new Master(); zhaosi.setName("赵四"); // 多态向上转型 父类引用指向子类对象 // 此时当前对象可以调用的是子类重写父类的方法 // 以及继承自父类的方法 // 不能调用子类独有的方法 Pet dog = zhaosi.give("一等奖"); dog.print(); Pet penguin = zhaosi.give("二等奖"); penguin.print(); } }
3.2 向下转型
向上转型不能访问子类独有的方法,如需 访问,可以向下转型
强制类型转换
为了避免类型转换的错误 我们可以使用instanceof关键字判断类型
避免错误的产生
package com.qfedu.test5;
/**
* 狗类
* 属性
* 品种
* 行为:打印
* 无参构造
*/
public class Dog extends Pet{
private String strain;
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
public Dog() {}
public Dog(String name,int health,int love,String strain) {
super(name, health, love);
this.strain = strain;
}
@Override
public void print() {
super.print();
System.out.println("狗狗的品种是:" + strain);
}
public void toHospital() {
super.toHospital();
System.out.println("狗狗看病,吃药,吃骨头,健康值恢复!");
this.setHealth(100);
}
public void playFlyDisc() {
System.out.println("狗狗玩飞盘,很开心~");
}
}
package com.qfedu.test5;
public class Test1 {
public static void main(String[] args) {
Master zhaosi = new Master();
zhaosi.setName("赵四");
Pet pet1 = zhaosi.give("一等奖"); // 向上转型
pet1.print();
Dog dog = (Dog)pet1;// 向下转型
dog.playFlyDisc();
// 向下转型是将:指向子类对象的父类引用 转换为 子类类型
// 而不是 将一个父类引用父类对象转换为子类类型
// 当引用数据类型 强制类型转换 应该先使用instanceof关键字判断类型是否可以 正确转换
// 对象名 instanceof 类名
// 表示判断此对象是否属于此类型 如果是返回值为true 否则为false
Pet pet2 = new Pet();
if(pet2 instanceof Dog) {
Dog dog1 = (Dog) pet2;
}else {
System.out.println("类型错误,不能转换");
}
}
}