多态

一、面向对象的基本特征

  • 1、封装 和权限修饰符有关
  • 2、继承 extends
  • 3、多态
  • 多态:多种形式
  • 变量的引用形式:
  • (1)本态引用:左边的变量与右边的对象是同一种类型
  • (2)多态引用:左边的对象时父类类型,右边的对象时子类的对象
  • 多态表象出来的特征:
  • 编译的时候是按照父类类型进行编译
  • 执行的方法是子类重写的方法
  • 前提:继承,重写,多态引用
  • 用途:方法的动态绑定
public class TestPolymorphism {
	
	public static void main(String[] args) {
		//本态引用
		//Person p = new Person();
		//Woman w = new Woman();
		//Man m = new Man();
		
		//多态引用
		Person p2 = new Woman();
		Person p3 = new Man();
		
		 p2.eat();
		 p2.walk();
		 

	}

}
class Person{
	public void eat(){
		System.out.println("吃饭");
	}
	public void walk(){
		System.out.println("走路");
	}
	
}
class Woman extends Person{
	public void eat(){
		System.out.println("狼吞虎咽");
	}
	public void walk(){
		System.out.println("走小路");
	}
	public void buy(){
		System.out.println("买东西");
	}
	
}
class Man extends Person{
	public void eat(){
		System.out.println("吃汉堡");
	}
	public void walk(){
		System.out.println("走大路");
	}
	public void smoke(){
		System.out.println("抽烟");
	}
	
}

多态的好处:

  • 使程序员编写代码更灵活
  • 多态的应用:
  • (1)多态数组
    
  • 数组的元素是父亲的类型,实际上存储的是子类的对象
    
  • 用这样的数组可以统一管理所有子类的对象
    
public class TestUse {
	public static void maim(String[] args){
		/*
		 * 创建一个数组,可以存储各种图形对象,包括园对象,矩形对象。。。
		 */
		//本态数组
		//Circle[] yuans=new Circle[3];
		//Rectangle[] jus=new Rectangle[3];
		Graphic[] all=new Graphic[3];
		all[0]=new Circle(1.2);
		all[1]=new Rectangle(2,4);
		all[2]=new Circle(1.5);
		
		//遍历所有图形的面积
		for(int i=0;i<all.length;i++){
			System.out.println(all[i].getArea());
			
		}
		
		
	}

}
class Graphic{
	public double getArea(){
		return 0.0;//无意义,保证格式正确
	}
}
class Circle extends Graphic{
	private double radius;

	public Circle(double radius) {
		super();
		this.radius = radius;
	}
	public double getArea(){
		return 3.14*radius*radius;
	}
}
class Rectangle extends Graphic{
	private double length;
	private double width;
	public Rectangle(double length, double width) {
		super();
		this.length = length;
		this.width = width;
	}
	public double getArea(){
		return length*width;
	}
	
}

(2)多态参数:

  • 行参是父亲类型,实参是子类对象
    
public class TestUse2 {
	
	//这个方法检查所有的动物吃东西是否正常
			//没有多态就需要重载很多个
			/*
			 * public static void eat(Dog dog){
			 *      dog.eat();
			 * }
			 */
	public static void check(Animal a){
		a.eat();
	}
    public static void main(String[] args) {
    	check(new Dog());//隐含了,形参Animal a = 实参 new Dog()
    	check(new Cat());
    	
    	Dog d = new Dog();
    	check(d);
		
		

	}

}
class Animal{
	public void eat(){
		System.out.println("吃东西");
	}
	
}
class Dog extends Animal{
	public void eat(){
		System.out.println("啃骨头");
	}
	
}
class Cat extends Animal{
	public void eat(){
		System.out.println("吃鱼");
	}
}

练习1

1、 声明Traffic
 * public void drive()方法
 *2、 声明Car,Bicycle,甚至可以声明Car的各种子类,例如BMW,Benz等
 *3、在测试类中创建一个数组,有各种交通工具,遍历调用drive()方法
 */

public class Test01 {
	

	public static void main(String[] args) {
		Traffic[] all = new Traffic[3];
		all[0]=new Car();
		all[1]=new Bicycle();
		all[2]=new Car();
		
		all[0].drive();
		all[1].drive();
		
		
	}

}
class Traffic{
	public void drive(){
		System.out.println("您使用的是");
	}
}
class Car extends Traffic{
	public void drive(){
		System.out.println("私家车");
	}
}
class Bicycle extends Traffic{
	public void drive(){
		System.out.println("自行车");
	}
}


练习2

/*
 * 1、声明一个Person类,有一个方法
 * public void toilet(){
 * }
 * 2、声明一个Woman。Man类重写方法
 * 3、在测试类中声明一个方法
 * public static void gotoToilet(Person p){
 *      调用toilet方法
 * }
 * 
 */

public class Test02 {
	public static void gotoToilet(Person p){
		p.toilet();
		
	}

	public static void main(String[] args) {
		/*
		 * 另一种方法:
		 * Woman m = new Woman();
		 * gotoToile(m);//行参是Person类型,实在是Woman类型
		 */
		gotoToilet(new Woman());
		gotoToilet(new Man());
		

	}

}
class Person{
	public void toilet(){
		System.out.println("厕所");
	}
}
class Woman extends Person{
	public void toilet(){
		System.out.println("女生去女厕");
	}
}
class Man extends Person{
	public void toilet(){
		System.out.println("男生去男厕");
	}
}

数据类型的转换

  • 1、基本数据类型的转换
  • (1)自动类型转换
  • byte->short->int->long->float->double
  •   char->
    

*boolean不参与
*(2)强制类型转换
*double->float->long->int->short->byte

  •                     ->char
    
  • 2、引用数据类型
  • 父子类之间的转换:编译期间
  • (1)向上转型:从子类-》父类
  • 把子类的对象赋值给父类的变量时
    
  • (方便统一管理各种子类对象)
    
  • (2)向下转型:从父类-》子类
  • 把父类的变量赋值给子类的变量时
    
  • (只有先向上转型的才能向下转型)
    

*/

public class TestCasting {


	public static void main(String[] args) {
		//1.向上转型
		Person p = new Woman();//多态引用
		p.eat();
		p.walk();
		//向下转型
		//想要调用Woman的方法,编译时是Person类型,运行时是Woman类型,编译不通过
		Woman m = (Woman)p;   //Woman m = p;报错  int i = (int)num;
		m.buy();
		

	}

}
class Person{
	
	public void eat(){
		System.out.println("吃饭");
	}
	public void walk(){
		System.out.println("走路");
	}
	
}
class Woman extends Person{
	
	public void eat(){
		System.out.println("狼吞虎咽");
	}
	public void walk(){
		System.out.println("走小路");
	}
	public void buy(){
		System.out.println("买东西");
	}
	
}
class Man extends Person{
	public void eat(){
		System.out.println("吃汉堡");
	}
	public void walk(){
		System.out.println("走大路");
	}
	public void smoke(){
		System.out.println("抽烟");
	}
	
}


多态,重载,重写

package demo;

/*
 * 考核点:多态,重载,重写
 * 1、分析每个类都有什么方法
 * A类:
 *   public String show(D obj)
 *   public String show(A obj)
 * B类:
 * 	 public String show(D obj)
 *   public String show(A obj)重写
 *   public String show(B obj)
 * C类和D类,因为这里没有用它们的对象去调用方法,暂时不分析。
 * 
 * 2、继承关系
 * C-->B-->A
 * D-->B-->A
 * 
 * 3、如果出现重载的多个方法,会找其中类型最合适的
 * 
 * 4、分析代码
 * (1)a1.show(b),因为这里a1没有多态引用,编译时类型和运行时类型都是A类,只看A类的方法。
 * 此时b对象是B类型,那么public String show(A obj)这个方法最合适,因为b不能赋值给D子类的形参,只能自动向上转型为A类
 *
 * (2)a2.show(d),因为这里a2有多态,编译时类型是从A类型中寻找最合适的方法,运行时执行的B类的重写的方法(首先在A类中找到方法,如果B类重写了这个方法,就执行B类的方法),如果B类没有重写,还是执行的是A类的
 * 此时d对象是D类型,在A类中public String show(D obj)这个方法最合适。
 * 
 * (3)b.show(c),因为b没有多态,编译时类型和运行时类型都是B类,从B类中选择最合适的方法
 * 此时c对象是C类型,在B类中public String show(B obj)最合适的,因为C与B最近,比与A近
 * 
 * (4)b.show(d),因为b没有多态,编译时类型和运行时类型都是B类,从B类中选择最合适的方法
 * 此时d对象是D类型,在B类中public String show(D obj)最合适
 */
public class Test01 {
	public static void main(String[] args) {
		A a1 = new A();
		A a2 = new B();
		B b = new B();
		C c = new C();
		D d = new D();
		System.out.println("(1)" + a1.show(b));//a1没有多态引用,只看A类,b对象时B类型,b不能赋值给D的形参,只能向上自动转型为A类,public String show(A obj)方法   A and A
		System.out.println("(2)" + a2.show(d));//有多态引用,编译时看A类中找最合适的方法,运行时看B类的重写方法,此时B类没有重写 A and D
		System.out.println("(3)" + b.show(c));//没有多态引用,只看B类,c对象时C类型,c像转型为B类型   B and B
		System.out.println("(4)" + b.show(d));//B中有D类型的方法  A and D
	}
}
class A{
	public String show(D obj){
		return ("A and D");
	}
	public String show(A obj){
		return "A and A";
	}
}
class B extends A{
	public String show(B obj){
		return "B and B";
	}
	public String show(A obj){
		return "B and A";
	}
}
class C extends B{
	
}
class D extends B{
	
}

结果为:
(1)A and A
(2)A and D
(3)B and B
(4)A and D

package demo2;


public class Test02 {
	public static void main(String[] args) {
		A a1 = new A();
		A a2 = new B();
		B b = new B();
		C c = new C();
		D d = new D();
		System.out.println("(1)" + a1.show(b));//a1没有多态,只看A类, A  and A
		System.out.println("(2)" + a2.show(d));//a2有多态,编译时看A类,运行时看B类 ,A类选择public String show(A obj)方法,
		                                        //B类重写了该方法    B and A
		System.out.println("(3)" + b.show(c));  //b 没有多态,只看B类,B类有三个方法 public String show(C obj)  A and C
		System.out.println("(4)" + b.show(d));//b 没有多态,只看B类,B类有三个方法,public String show(B obj) B and B
	}
}

class A {
	public String show(C obj) {
		return ("A and C");
	}

	public String show(A obj) {
		return "A and A";
	}
}

class B extends A {
	public String show(B obj) {
		return "B and B";
	}

	public String show(A obj) {
		return "B and A";
	}
}

class C extends B {

}

class D extends B {

}

(1)A and A
(2)B and A
(3)A and C
(4)B and B

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值