一篇文章带你学懂多态

多态的应用

多态的基本语法

多态在开发中的作用

多态

多态的应用
Animal父类

public class Animal
{
	public void move(){
		System.out.println("动物正在移动!!!!");
	}
}

Bird子类

public class Bird extends Animal
{
	public void move(){
		System.out.println("鸟儿在飞翔!!!!");
	}
    public void sing(){
		System.out.println("鸟儿在歌唱");
	}
}

Cat子类

public class Cat extends Animal
{
	public void move(){
		System.out.println("猫儿在走猫步!!!!");
	}
    public void catMouse(){
		System.out.println("猫在抓老鼠");
	}
}

测试类

public class Test1
{
	public static void main(String[] args){
		Animal a1=new Animal();
		Animal a2=new Bird();//向上转型
		Animal a3=new Cat();//向上转型
		a1.move();
		a2.move();
		a3.move();

		// 错误: 找不到符号
       //a4.sing();
	   //类型为Animal的变量 a4
		/*
		Animal a4=new Bird();
		a4.sing();
		这里sing方法是子类所特有的方法,不能a4.sing();
		因为这样的话过不了编译阶段,编译阶段是静态绑定,
		a4是Animal引用,编译阶段在Animal中找不到sing方法
		*/

		//要真的实在是想用子类中特有的方法的话就需要向下转型
		//如下

		Animal a5=new Bird();
		Bird x=(Bird)a5;//这里就是向下转型
		x.sing();//这样就可以访问子类中特有的方法


		//这样向下转型会不会有风险?
		//当然是会有风险的
		//比如下面情况;

		/*
		Animal a6=new Cat();
		Bird y=(Bird)a6;
		*/
		
		//虽然能过编译,但是不能过运行阶段,会报异常java.lang.ClassCastException类转换异常
		// java.lang.ClassCastException: Cat cannot be cast to Bird
        //at Test1.main(Test1.java:34)


		//避免java.lang.ClassCastException这个异常需要使用instanceof运算符
		Animal a7=new Cat();
		if(a7 instanceof Bird){
			Bird n=(Bird)a7;
			n.sing();
		}else if(a7 instanceof Cat){
			Cat m=(Cat)a7;
			m.catMouse();
		}//分支判断,a7引用指向堆内存中的java对象是Cat





	
	
	}
}

多态的基础语法

经过测试可知java中支持这样的一个语法:父类型的引用允许指向子类型的对象

多态:

1、父类型的引用指向子类型的对象

2、包括编译阶段和运行阶段

3、编译阶段:绑定父类的方法(静态绑定)

4、运行阶段:绑定子类型对象的方法(动态绑定)运行阶段(堆内存当中创建对象)

5、多种形态

java中允许向上转型也允许向下转型

**ps:**无论是向上转型还是向下转型,两种类型之间必须有继承关系,没有继承关系的话编译器会报错

向上转型(upcasting)

子类--------->父类

例如:

Animal是父类

Cat是子类

Animal a1=new Cat();//这个就是向上转型,父类型的引用指向子类型的对象

a1.方法(这个方法是父类有的,而不能是子类所特有的)

如果引用的对象是子类特有的话,编译器会报错,错误:找不到符号

new Cat()就是子类型的对象

Animal a1就是父类型的引用

这里在编译阶段,会先去找父类中的有没有这个方法,然后在运行阶段就会再动态的绑定子类型对象中的方法

向上转型有风险吗?

编译不报错,没有风险

向下转型(downcasting)

什么时候使用向下转型:

如果想访问的方法是子类所特有的,就需要使用向下转型

例如

Cat a2=new Cat();

Cat x=(Cat)a2;(这里就是进行了强制类型转换也称向下转型)

x.方法(这个方法就是子类Cat所特有的方法)

向下转型有风险吗?

有风险

Animal a3=new Bird();//这里的Animal是一个父类,Bird是继承Animal的子类,这里是向上转型

//这里编译阶段不会报错,但是运行阶段会报错,在运行阶段中,堆内存实际创建的对象是Bird对象,在实际运行中,拿着Bird对象转化成Cat对象就不行了。因为Bird对象和Cat对象没有继承关系。
//运行出现异常:这个异常和空指针异常一样非常重要,也非常经典
//java.lang.ClassCaseException:类型转换异常
Cat y=(Cat)a3;
y.catMouse();
如何避免ClassCaseException异常的发生

运算符:instanceof(主要是在运行阶段动态判断引用指向的对象类型)

语法:(引用 instanceof 类型)这个的返回结果是true/false

假设c是一个引用,c变量保存的内存地址指向堆中对象

1、假设(c instanceof Cat)为true时,表示:c引用指向的堆内存中的java对象是一个Cat

2、假设(c instanceof Cat)为false时,表示的是:c引用指向的堆内存中的java对象不是一个Cat

程序员需要养成一个习惯:

在任何时候,任何地点,对类型进行向下转型时,一定要使用instanceof运算符进行判断,(这是java规范中要求的)

这样可以很好的避免:ClassCaseException异常

为什么要使用instanceof

因为有些时候程序员编写程序不是一个人而是分工完成的,所以当一个程序员在编程方法的时候他是不知道类的继承关系,以及进行向下转型会不会出错的,这个时候就需要使用instanceof来进行判断。

就例如;

一个人编写AnimalTest类

public class AnimalTest
{

	//这个方法里面的参数是引用数据类型
	//a就是相当于 Animal a =new Cat();/new Bird();
	public void test(Animal a){
		//为什么要用instanceof?
		//因为这个程序时多人编写,别人不一定能知道传进来的参数继承的是哪个类,
		//可不可以进行向下转换,并调用独有方法

		if(a instanceof Cat){
			Cat x=(Cat)a;
			x.catMouse();
		}else if(a instanceof Bird){
			Bird y=(Bird)a;
			y.sing();
		}
	
	
	}
}

一个人编写Test2类

public class Test2
{
	public static void main(String[] args){
		//new出AnimalTest对象
		AnimalTest a1=new AnimalTest();
		AnimalTest a2=new AnimalTest();

		//对象调用方法,传的是引用数据类型
		a1.test(new Cat());//猫在抓老鼠
		a2.test(new Bird());//鸟儿在歌唱


	}
}

多态在开发中的作用:非常重要*********

一个好的软件就是要尽可能的减少对类的修改(除了添加类)要遵循ocp原则。
而多态就是为了能够降低程序的耦合度,提高程序的扩展力

例子:

编写程序模拟“主人”喂养“宠物”的场景:
提示1:
主人类:Master
宠物类:Pet
宠物类子类:Dog、Cat、YingWu
提示2:
主人应该有喂养的方法:feed()
宠物应该有吃的方法:eat()
只要主人喂宠物,宠物就吃。

要求:主人类中只提供一个喂养方法feed(),要求达到可以喂养各种类型的宠物。

编写测试程序:
创建主人对象
创建各种宠物对象
调用主人的喂养方法feed(),喂养不同的宠物,观察执行结果。

类Master

public class Master{
	public void feed(Pet pet){
		pet.eat();
	
	}
}

类Pet

public class Pet{
	public void eat(){}
}

类Dog

public class Dog extends Pet
{
	public void eat(){
		System.out.println("狗狗喜欢吃骨头,吃的很香!!!");
	}
}

类Cat

public class Cat extends Pet
{
	public void eat(){
		System.out.println("猫猫喜欢吃小鱼干,吃的很香!!!");
	}
}

类YingWu

public class YingWu extends Pet
{
	public void eat(){
		System.out.println("鹦鹉喜欢吃小虫子,吃的很香!!!");
	}
}

测试类Test1

public class Test1
{
	public static void main(String[] args){
		//创建类的对象
		Master xiaoming=new Master();
		Dog heibei=new Dog();
		Cat xiaomao=new Cat();
		YingWu yingWu=new YingWu();
		xiaoming.feed(heibei);
		xiaoming.feed(xiaomao);
		xiaoming.feed(yingWu);

	
	
	}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值