JAVA的多态

== 什么是多态==
多态是具有表现多种形态的能力的特征,更专业的说话,同一个实现接口,使用不同的实例而执行不同的操作。

下面的图将有助于我们理解多态:
在这里插入图片描述
对图进行解释:打印机可以看做父类,黑白打印机,彩色打印机是它的两个子类,父类打印机中的方法“打印”在每个子类中有不同的实现方式。

子类到父类的转换(向上转换)
实际上,在引用数据类型的子类和父类之间,也存在着类型转换,如以下代码:

Dog dog=new Dog("欧欧","雪纳瑞");//不涉及类型转换
dog.eat();
Pet pet=new Dog("欧欧","雪纳瑞");//子类到父类的转换
pet.eat();//会调用Dog类重写的eat()方法,而不是eat类的eat()方法。
pet.CatChingDisc();//编译错误,父类的引用无法调用子类特有的方法。

下面我们将进一步的证明来更深刻的理解以上代码:
1.Pet pet=new Dog(“欧欧”,“雪纳瑞”);
主人需要一只宠物,一条狗狗肯定符合其要求,不用特别声明,所以可以直接将子类对象赋给父类引用变量。
2.pet.eat();
主人给宠物喂食时看到的肯定是狗狗在吃饭而不是企鹅在吃饭,也不是抽象的pet在吃饭。
3.pet.CatChingDisc();
假定主人可以同时和狗狗和企鹅喂食,但只能和狗狗玩接飞盘游戏,只能和企鹅玩游泳游戏,在没有判定宠物是狗狗时,主人不能和宠物玩飞盘游戏,因为他需要的是一只宠物,但是没有明确需求需要一条狗狗,所以很有可能得到的是一只企鹅,因此不能确定是玩接飞盘游戏还是游泳游戏。

使用父类作为方法形参实现多态

代码如下:

/*
 * 宠物类,狗狗和企鹅的父类
 */
public abstract class Pet {
	protected String name="无名氏";
	protected int health=100;
	protected int love=0;
	public Pet(String name){
		this.name=name;
	}
	
	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 void print(){
		System.out.println("宠物的自白:\n我的名字叫"+this.name+",健康值是"+this.health+",和主人的亲密度是"+this.love+"。");
	}
	/*
	 * 抽象方法eat(),负责宠物吃饭功能
	 */
	public abstract void eat();
}


让Dog类重写Pet类的eat()方法,实现狗狗吃饭功能,代码如下:
/*
 * 狗狗类,宠物的子类
 */
public class Dog extends Pet {
	private String strain;//品种
	public Dog(String name,String strain){
		super(name);
		this.strain=strain;
	}
	/*
	 * 重写父类的print()方法
	 */
	public void print(){
		super.print();//调用父类的print方法
		System.out.println("我是一只"+this.strain+"。");
	}
	/*
	 * 实现狗狗吃饭的方法
	 */
	public void eat(){
		super.health=super.health+3;
		System.out.println("狗狗"+super.name+"吃饱啦!健康值加3");
	}
}


让Penguin类重写Pet类的eat()方法,实现企鹅吃放功能,代码如下:
/*
 * 企鹅类,宠物的子类
 */
public class Penguin extends Pet {
	private String sex;//性别
	public Penguin(String name,String sex){
		super(name);
		this.sex=sex;
	}
	/*
	 *重写父类的print()方法
	 */
	public void print(){
		super.print();
		System.out.println("性别是"+this.sex+"。");
	}
	/*
	 * 实现企鹅吃饭的方法
	 */
	public void eat(){
		super.health=super.health+5;
		System.out.println("企鹅"+super.name+"吃饱啦!健康值加3");
	}
}


创建主人类Master,在类中添加feed(Dog dog)方法,调用Dog类的eat()方法,实现狗狗的喂养,添加feed(Penguin pgn)方法,调用Penguin类的eat()方法,实现企鹅的喂养
/*
 * 主人类
 */
public class Master {
	private String name="";//主人名字
	private int money=0;//元宝数
	public Master(String name,int money){
		this.name=name;
		this.money=money;
	}
	/*
	 * 主人给宠物喂食
	 */
	public void feed(Pet pet){
		pet.eat();
	}
	/*
	 * 主人给Dog喂食
	 */
	public void feed(Dog dog){
		dog.eat();
	}
	/*
	 * 主人给Penguin喂食
	 */
	public void feed(Penguin pgn){
		pgn.eat();
	}


测试类代码如下:
public class Test {

	public static void main(String[] args) {
		Pet pet=new Dog("欧欧","雪纳瑞");
		//Penguin pgn=new Penguin("楠楠","Q妹");
		Master master=new Master("王先生",100);
		master.feed(pet);//主人给宠物喂食

运行结果为:狗狗欧欧吃饱啦!健康值加3
如果将"Pet pet=new Dog(“欧欧”,“雪纳瑞”);“这一行注释掉,取消”//Penguin pgn=new Penguin(“楠楠”,“Q妹”);"这一行的注释
运行结果为:企鹅楠楠吃饱啦!健康值加5

由此我们可以看出使用父类作为方法形参的优势,或者说是使用多态的优势:可以减少代码量,提高代码的可扩展性和可维护性。

即使增加子类也无需添加或者修改feed()方法,为了证明这一点,我们来添加宠物Cat类,继承Pet并重写eat()方法。
代码如下:

/*
 * 猫类,宠物的子类
 */
public class Cat extends Pet {
	private String color;//颜色
	public Cat(String name,String color){
		super(name);
		this.color=color;
	}
	/*
	 * 实现吃饭的方法
	 */
	public void eat(){
		super.health=super.health+4;
		System.out.println("猫咪"+super.name+"吃饱啦!健康值加4。");
	}
}

测试类代码如下:
public class Test {

	public static void main(String[] args) {
		//Pet pet=new Dog("欧欧","雪纳瑞");
		//Penguin pgn=new Penguin("楠楠","Q妹");
		Master master=new Master("王先生",100);
		Pet pet=new Cat("粒粒","黄色");
		master.feed(pet);//主人给宠物喂食

运行结果为:猫咪粒粒吃饱啦!健康值加4。

通过上面的介绍大家对多态的特点是不是有了更深入的了解呢?下面让我们学习多态的另一种场合。

使用父类作为方法返回值实现多态

先修改Master类添加getPet(String tupeId)方法,以父类Pet作为返回值类型实现领养功能,代码如下:

/*
 * 主人类
 */
public class Master {
	private String name="";//主人名字
	private int money=0;//元宝数
	public Master(String name,int money){
		this.name=name;
		this.money=money;
	}
	/*
	 * 主人领养宠物
	 */
	public Pet getPet(int typeId){
		Pet pet=null;
		if(typeId==1){
			pet=new Dog("欧欧","雪纳瑞");
		}else if(typeId==2){
			pet=new Penguin("楠楠","Q妹");
		}
		return pet;
	}
	/*
	 * 主人给宠物喂食
	 */
	public void feed(Pet pet){
		pet.eat();
	}
	/*
	 * 主人给Dog喂食
	 */
	public void feed(Dog dog){
		dog.eat();
	}
	/*
	 * 主人给Penguin喂食
	 */
	public void feed(Penguin pgn){
		pgn.eat();
	}

在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.println("请选择要领养的宠物类型:(1.狗狗 2.企鹅)");
	int typeId=input.nextInt();
	Pet pet=master.getPet(typeId);
	if(pet!=null){
		System.out.println("领养成功");
		master.feed(pet);
	}
	else{
		System.out.println("对不起,没有此类型的宠物,领养失败");
		}
	}
}


运行结果如下:
在这里插入图片描述
通过以上的示例对多态功能的详解,总结出实现多态的三个条件
1.继承的存在(继承是多态的基础,没有继承就没有多态)
2.子类重写父类的方法(多态下调用自类重写后的方法)
3.父类引用变量指向子类对象(子类到父类的类型转换)

instanceof运算符

当进行向下转型时,如果没有转换为真实子类类型,就会出现类型转换异常。Java提供了 instanceof运算符来进行类型的判断。

语法:
对象 instanceof 类和接口
该运算符用来判断一个对象是否属于一个类或者实现了一个接口,结果为true或false,在强制类型转换之前通过 instanceof运算符检查对象的真实类型,从而额提高代码的健壮性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值