多态
概念:父类引用子类对象,从而产生多种形态
前提:二者之间必须具有直接或间接的继承关系,父类引用可指向子类对象,进而形成多态。
注意:父类引用仅可调用父类中所声明的属性和方法,不可调用子类独有的属性和方法。
多态的两种应用场景
场景一:使用父类作为方法形参,实现多态。使方法的类型更为广泛。
场景二:使用父类作为方法返回值实现多态,使方法可以返回不同子类对象。
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类型结果