ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多态

2021-11-06 21:04:50  阅读:157  来源: 互联网

标签:void move 多态 Cat a1 Animal public


多态

1. 向上/下转型(前提:两种类型之间有继承关系)

1. 向上转型 子转向父

public class Animal {//父类
	public void move() {
		System.out.println("动物在移动");
	}
	public static void main(String [] args) {
		Animal a1=new  Bird();
		Animal a2=new  Cat();
		a1.move();//鸟在飞翔
		a2.move();//猫在走猫步		
	}
}
 class Bird extends Animal {
	 public void move() {
		 System.out.println("鸟在飞翔");
	 }
	 
}
 class Cat extends Animal {
	 public void move() {
		 System.out.println("猫在走猫步");
	 }
}

Animal a1=new Bird();
其中,Animal是父类, Bird是子类,满足继承关系的前提
a1是父类型的引用,new Bird()是子类型的对象
此时,多态中是父类型的引用指向子类型的对象
分析:a1.move();
java程序分为编译阶段和运行阶段

  1. 编译阶段:对于编译器,只知道a1的类型是Animal,所以编译器在检查语法时,会去Animal.class字节码文件中去找move()方法,找到了,就绑定上move()方法,编译通过,静态绑定成功
  2. 运行阶段:实际上在堆内存中创建的java对象是 Bird对象,所以在执行move()方法时,真正执行move()方法的对象是Bird对象,属于运行阶段绑定,动态绑定
    **多态体现在:编译的时候一种形态,运行的时候是另一种形态
    多态指的是是父类型的引用指向子类型的对象,包括编译阶段和运行阶段,编译阶段静态绑定父类的方法,运行阶段动态绑定子类型对象的方法 **

2. 向下转型 父转向子

当想要访问子类对象特有的方法,要向下转型

public class Animal {//父类
	public void move() {
		System.out.println("动物在移动");
	}
	public static void main(String [] args) {
		Animal a1=new Cat();
		//a1.zhua();不执行,为什么?
		/*分析程序要分编译阶段静态绑定和运行阶段的动态绑定
		 * 在编译阶段,编译器,只知道a1的类型是Animal,
		 * 会去Animal.class字节码文件中去找zhua()方法,没有找到,编译不通过
		 * 要想可以执行,使用向下转型,类似于强制类型转换
		 * 当想要访问子类对象特有的方法,要向下转型*/
		Cat x = (Cat)a1;
		x.zhua();//猫在抓老鼠
		/*分析:a1的类型是Animal,Animal和a1满足继承关系,可以向下转型*/
	}
}
 class Cat extends Animal {
	 public void move() {//父类方法重写
		 System.out.println("猫在走猫步");
	 }
	 //子类独有的方法
	 public void zhua() {
		 System.out.println("猫在抓老鼠");
	 }
}

instanceof运算符

  1. instanceof可以在运行阶段动态判断引用指向的对象的类型
  2. 语法: (引用 intanceof 类型)
  3. 运算结果是true或false
  4. (引用 instanceof 类型)若为true,表明引用所保存的内存地址指向的堆中的对象是属于此类型
 public class Animal {//父类
	public void move() {
		System.out.println("动物在移动");
	}
	public static void main(String [] args) {
		Animal a1= new  Bird();
//		Cat y = (Cat)a1;
//		y.zhua();
/*分析:a1的类型是Animal,Animal和a1满足继承关系,可以向下转型,编译通过
 * 运行阶段:堆内存中实际上创建的对象是 Bird对象,要将 Bird对象转换为Cat,
 * 二者之间没有继承关系,就不行了,
 * 运行报错 java.lang.ClassCastException称为类型转换异常
 * 以上称为向下转型的风险/
 * 避免异常的发生?用到ins/tanceof运算符*/
		if(a1 instanceof Cat) {
			Cat y = (Cat)a1;
			y.zhua();
		}//在以后进行向下转型时,要写的判断语句
		else {
			System.out.println("a1指向的对象不是猫类型");
		}
	}//a1指向的对象不是猫类型
}
 class Bird extends Animal {
	 public void move() {
		 System.out.println("鸟在飞翔");
	 }	 
}
 class Cat extends Animal {
	 public void move() {
		 System.out.println("猫在走猫步");
	 }
	 public void zhua() {
		 System.out.println("猫在抓老鼠");
	 }
}
  1. 虽然自己肉眼可以观察到底层是 new Bird()还是new Cat(),但以后程序交接给别人时,不知道,所以要习惯上用instanceof运算符去判断
 public class Animal {//父类
	public void move() {
		System.out.println("动物在移动");
	}
	public static void main(String [] args) {
		Animal x=new  Bird();
		if(x instanceof Bird) {
			Bird  b= (Bird)x;
			b.sing();
		}
		else if(x instanceof Cat) {
			Cat a=(Cat)x;
			a.zhua();
		}
}
 class Bird extends Animal {
	 public void move() {
		 System.out.println("鸟在飞翔");
	 }	
	 public void sing() {
		 System.out.println("猫在抓老鼠");
	 }	 
}
 class Cat extends Animal {
	 public void move() {
		 System.out.println("猫在走猫步");
	 }
	 public void zhua() {
		 System.out.println("猫在抓老鼠");
	 }
}

多态在开发中的作用

  1. 在软件开发中有一个原则:OCP(开闭原则):
    对扩展开放(可以额外添加程序)
    对修改关闭(最好少修改现有的程序)
    开发项目在满足客户需求的同时,还要考虑软件的扩展性
  2. 例如:在主人喂养宠物的案例中,在程序主人源程序中不写具体的宠物,可以写一个宠物父类,

public class Test {
	public static void main(String[] args) {
		 //创建主人对象
		Master zhang = new Master();
		//创建宠物对象
		Cat xiao = new Cat();
		Dog huang = new Dog();
		//主人喂宠物
		zhang.feed(xiao);
		zhang.feed(huang);
	}
}
class Master{
	public void feed(Pet p) {
		p.eat();
	}
}
class Pet{//所有宠物的父类
	//包含了吃的行为
	public void eat(){
		
	}
}
//具体的宠物对象继承父类Pet,重写父类中的方法
class Cat extends Pet{
      public void eat(){
		System.out.println("猫吃鱼");
	}
}
class Dog extends Pet{
public void eat(){
		System.out.println("狗吃骨头");
	}
}

多态体现在zhang.feed(xiao)中,对象xiao传参给(Pet p)相当于
Pet p = new Cat()
编译时:编译器会知道 p是属于Pet类,会去Pet这个父类中去查找 eat()方法,找到了,编译通过
运行时:底层实际对象是什么,就自动调用到该实际对象的 eat()方法上
这就是多态的使用
以后客户有了新的需求,不需要修改客户类,就继承宠物父类,对它的方法进行重写,重新创建一个新的宠物对象就行了
多态可以降低程序的耦合度,提高成序的扩展力
补:

  1. 方法覆盖常常和多态联合起来,而多态就强调对象,而静态方法的调用不需要对象来调用,所以常说方法覆盖只是针对实例方法,静态方法的覆盖无意义
  2. 私有方法不能覆盖 静态不谈覆盖

面向对象的三大特征:

封装, 继承, 多态
有了封装,就有了整体的概念之后,对象和对象之间产生了继承,之后才有了方法覆盖和多态

标签:void,move,多态,Cat,a1,Animal,public
来源: https://www.cnblogs.com/yang123-456/p/15518329.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有