多态的理解

多态

概念:父类引用子类对象,从而产生多种形态

前提:二者之间必须具有直接或间接的继承关系,父类引用可指向子类对象,进而形成多态。

注意:父类引用仅可调用父类中所声明的属性和方法,不可调用子类独有的属性和方法。

多态的两种应用场景

场景一:使用父类作为方法形参,实现多态。使方法的类型更为广泛。

场景二:使用父类作为方法返回值实现多态,使方法可以返回不同子类对象。

public class TestPolym {
	public static void main(String[] args) {
		//-------------------多态的规则------------------
		Car car = new Car();  //自身类型指向自身类型对象
		car.type = "小汽车";
		car.speed = 120;
		car.price = 100000;
		car.brand = "BMW"; //独有属性
//		car.run();
		
		Vehicle vehicle = new Car();	//父类引用指向子类对象
		vehicle.type = "小汽车";
		vehicle.speed = 100;
		vehicle.price = 200000;
		vehicle.run();	//多态场景下,父类引用调用方法,如果被子类覆盖过,优先调用子类重写的方法
		
		//---------------------- 场景一 ----------------------
		Bus bus = new Bus();
		bus.type = "公交车";
		bus.speed = 40;
		bus.price = 1000000;
		bus.seatNum = 20;
		
		//场景一:父类作为方法的形参作为参数
		Employee employee = new Employee(); //员工对象
		employee.name = "小武";
		employee.goHome(bus);
		employee.goHome(car);

		//---------------------- 场景二 ---------------------
		Employee employee2 = new Employee(); 
		employee2.name = "小史";
		Vehicle myVehicle = employee2.buyVehicle(10);
		if (myVehicle != null) {
			employee2.goHome(myVehicle);
		}else {
			System.out.println("钱不够,买不成");
		}
        
        //拆箱:将父类引用中的真实子类对象转回其本身类型
		if(myVehicle instanceof Car) {  //判断myVehicle引用中的真实子类对象,是否为Car类型
			Car myCar = (Car) myVehicle;
		}else if (myVehicle instanceof Bus) {
			Bus myBus = (Bus) myVehicle;
		}
	}
}

/**
 * 这个员工类有个方法要回家
 * 回家会选择不同的交通工具,就要传入不同的交通对象,导致耦合度高
 * 		但是gohome这个方法与传入的交通工具对象是一种松散的关系,我选择哪个对象都是可以的
 * 		这样我们就可以选择父类作为方法的形参,就可以选择传入不同的子类对象。
 */
class Employee{
	String name; //员工名
    /*
     场景一:父类类型作为方法形参,实现多态 (员工回家)
    */
	public void goHome(Vehicle veh) {
		System.out.print(name + "正在乘坐");
		veh.run();
	}
	/**
	 * 降低了耦合度
	 * 不然Employee创建一个类就要创建一个传入的参数
	 */
//	public void gohome(Car car) {   //传入Car类型的参数
//		System.out.print(name + "正在乘坐");
//		car.run();
//	}
    
    /*
    	场景二:使用父类作为返回值实现多态,使方法可以返回不同的子类对象  (员工买车新)
    */
	public Vehicle buyVehicle(int money) {
		Vehicle vehicle = null;
		if (money >= 100) {
			Bus bus = new Bus();
			bus.type = "公交车";
			bus.speed = 50;
			bus.price = 1000000;
			bus.seatNum = 20;
			vehicle = bus;		//将创建的bus对象保存到vehcle引用里,本身是向上转型
		}else if (money >= 30) {
			Car car = new Car();
			car.type = "小汽车";
			car.speed = 120;
			car.price = 500000;
			car.brand = "BWM";
            vehicle = car;		//将创建的car对象保存到vehcle引用里
		}
		return vehicle;
	}
    
	
}
//交通工具类
class Vehicle{   
	String type; //类型
	int speed;  //速度
	double price;  //价格
	
	//父类的方法
	public void run() {
		System.out.println("一辆价值" + price + "Rmb的" + type + "正在以" + speed + "速度前进");
	}
}

//实体类Car继承交通工具父类
class Car extends Vehicle{
	String brand;	//品牌
	
	//重写父类的方法
	@Override
	public void run() {
		System.out.println("一辆价值" + price + "Rmb的" + brand + "品牌的"+ type + "正在以" + speed + "速度前进");
	}
}

//实体类Bus继承交通工具父类
class Bus extends Vehicle{
	int seatNum;
	//重写父类的方法
	@Override
	public void run() {
		System.out.println("一辆价值" + price + "Rmb的" + seatNum + "座位的" + type + "正在以" + speed + "速度前进");
	}
}

多态的装箱和拆箱

向上转型(装箱)

父类引用中保存真实子类对象,称为向上转型(即多态核心概念)。

Animal a = new Dog();  //小转大

向下转型(拆箱)

将父类引用中的真实子类对象,强转回类本身类型,称为向下转型。

Animal a = new Dog();
Dog dog = (Dog)a;   //大转小

为什么会有向下转型?

因为我们的父类引用中明明保存这子类对象的属性,却不能访问他的属性和方法,但是又有这种需求,此时我们就需要转回子类真是类型,才可与调用子类独有的属性和方法。

instanceof关键字

向下转型前,应判断引用中的对象真实类型,保证转换的真实性。

语法:父类引用 instanceof 类型

​ 返回boolean类型结果

原文地址:https://www.cnblogs.com/MonkeySun/p/13233818.html