多态: 提高代码的扩展性
多态的好处和弊端
不使用多态:
好处: 可以调用子类的特有行为
弊端: 扩展性极差
使用多态:
好处: 扩展性强
弊端: 不可以调用子类的特有行为
多态的概念:同一行为,通过不同的事物,可以体现出来的不同的形态。
你自己 在餐馆中: 是一个顾客 在公司中: 是一个员工 回老家: 是一个孩子
//不是多态 左侧是Student类型,右侧是Student对象,左右一致
Student stu = new Student();
//是多态 左侧是Person类型,右侧是Student对象,左右不一致,左边是父类,右边是子类对象
Person p = new Student();
多态的前提:
(1)必须要有继承或者接口实现
(2)必须要有父类引用指向子类对象(父类类型的变量保存子类对象的地址值)
(3)必须要有方法的覆盖重写,否则将失去多态的意义
(2)多态的方式调用方法,方法跟着对象走
父类 Person 定义抽象父类 Person
子类 public class Student extends Person {
测试类 //多态的方式创建Student类的对象
//Person类型变量保存子类Student类型的对象
Person 父类 p = new Student子类();
p.eat();
//Person类型变量保存子类Teacher类型的对象
p = new Teacher();
p.eat();
多态中成员方法的访问特点【重点】
编译时期: 检测父类Animal02中是否有kanHome方法的定义
发现父类中: 有sleep方法的定义,编译通过
发现父类中: 没有kanHome方法的定义,编译报错
//1不使用多态
Dog dog = new Dog();
dog.sleep();
//dog = new Cat();错误: 左右两边类型不匹配
//使用多态
Animal a = new Dog();
a.eat();
a.sleep();
//重新把Cat对象保存到父类Animal变量a中
a = new Cat();
a.eat();
a.sleep();
多态中的向上向下转型
暴露新的问题:Animal 方法内部不能直接调用子类的特有行为kanHome了 解决---多态中的向上转型
暴露新的问题:Animal 方法内部不能直接调用子类的特有行为kanHome了
解决---多态中的向上转型
//a.kanHome();---错误
多态中的向上转型 类引用指向子类对象)
public class Demo06DuoTai {
public static void main(String[] args) {
//多态的方式创建Animal类型的对象: 向上转型
Animal a = new Dog();
//此时只能直接调用Animal中规定好的方法
a.eat();
a.sleep();
//a.kanHome(); 报错把Cat对象重新存储到Animal变量中
a = new Cat();
//向下转型: 把Animal类型的变量a,强制转换成Dog类型
Dog dog = (Dog)a;
//就可以调用Dog类的特有行为了
dog.kanHome();
}
}
多态中的向下转型 强制类型转换
取值范围大的数据或者变量不可以直接赋值给取值范围小的变量
double d2 = 100;//double: 占8个字节
int c = (int)d2;//int: 占4个字节
强制类型转换:
转后类型 对象名称 = (转后类型)转前的对象或者变量名称;
注意:多态的向下转型(强制类型转换)存在安全隐患
如果转换前的类型和转换后的类型不一致,就会报出类型转换异常(ClassCastException)
方法内部不能直接调用子类的特有行为了 如何解决这个问题呢?---- 使用instanceof关键字
如何解决呢?
如果变量a指向的是Dog类型,把Animal类型的变量a强制转换成Dog类型
如果变量a指向的是Cat类型,把Animal类型的变量b强制转换成Cat类型
如何判断变量a指向的到底是哪种类型的对象呢?
使用instanceof关键字
使用格式:
boolean result = 对象名 instanceof 类名
如果对象名称中保存的是该类的对象,返回true。
如果对象名称中保存的不是该类的对象,返回false。
//测试类
public class Demo07DuoTai {
public static void main(String[] args) {
//多态的方式创建Animal类型的对象: 向上转型
//Animal a = new Dog();
Animal a = new Cat();
//此时只能直接调用Animal中规定好的方法
a.eat();
a.sleep();
//如果引用变量a存储的是Dog类型的变量
if (a instanceof Dog) {
//向下转型: 把Animal类型的变量a,强制转换成Dog类型
Dog dog = (Dog)a;
//就可以调用Dog类的特有行为了
dog.kanHome();
}
//如果引用变量a存储的是Cat类型的变量
if (a instanceof Cat) {
//向下转型: 把Animal类型的变量a,强制转换成Cat类型
Cat cat = (Cat)a;
//就可以调用Cat类的特有行为了
cat.catchMouse();
}
}
}