1.面向对象的三大特征之一 :封装 继承 多态
2.含义就是: 对象的多种形态
理解会发现狗类是动物类,猫类也可以是动物类
Dog dag = new Dog(); 这是常态
Animal a = new Dog(); 这是多态
Animal a = new Cat(): 这也是多态
3.多态的前提条件:
1. 两个类必须有继承(extends)实现(implements)关系,不是任何类都可以进行多态指向另一个类,
2.书写格式 必须是父类类型的变量指向子类类型的对象 Animal a = new Cat()
3.就是存在方法的重写
重写就是在子类中有和父类相同的方法,名称相同,参数相同,用@Overrivde注解检查重写,(注意子类的修饰符大于父类,返回值小于父类的返回值)
4.语法形式
父类类型 变量名称 = new 子类构造器
接口 变量名称 = new 类构造器
5.多态的调用方式
1.对于方法的调用:编译看左边,执行看右边(编译就是检查代码错误,生成class,执行的结果看右边子类的方法)
2.对于变量的调用:编译看左边,执行也看左边 (解释调用变量发现全是父类的值)
6.多态的优势和弊端
1.解耦合(类于类之间把关联依赖降到最低,尽量不出现动一发而动全身)
2.多态下父类类型作为方法的入参,可以接受一切子类对象,更利于方法的扩展和便利(比如调用一个方法里面接收参数是父类,method(Animal a) 调用这个方法子类都可以传进去 )
3.弊端
我们用变量名称调用子类的独有方法(并没有重写),是调不到的
Animal a = new Lv();
a.Lv类独有的方法 //调不到
package com.itheima.day02.teacher.duotai02;
/**
* 动物类
*/
public class Animal {
public void load(){
System.out.println("动物叫.....");
}
public void sleep(){
System.out.println("静静睡觉....");
}
}
---------------
package com.itheima.day02.teacher.duotai02;
/**
* 驴类
*/
public class Lv extends Animal {
// 因为驴的叫声 别致 所以重写 叫的方法
@Override
public void load() {
System.out.println("a~o~哦!~啊~额~~哦~~~");
}
public void laMo(){
System.out.println("懒驴拉磨...屎尿多....");
}
}
----------------
package com.itheima.day02.teacher.duotai02;
/**
* 测试类
*/
public class Demo02 {
public static void main(String[] args) {
//Lv()
Animal a = new Lv();//向上转型
a.load();
a.sleep();
//拉磨
// a.laMo();//编译期报错 --检查语法问题
// 现在是动物的形态 动物不会拉磨的
// 编译只看 多态式子的左边 检查左边的这个类型里面是不是有 该方法
// 多态的弊端 在父类形态下 只能使用父类的功能 无法使用子类特有功能
/*
向上转型 -- 自动转型--多态形式
父类类型 变量名 = 子类对象。
向下转型 -- 强制转换 -- 还原回去
子类类型 变量名 = (子类类型)父类变量;
*/
Lv lv = (Lv)a;
lv.laMo();
//类型转换 作用 还原会子类类型 调用子类特有功能
}
}
7.关于多态的弊端解决方式
1. 转换我们的类型
2.转换方式
1.向上转型,也叫自动转型 Animal a = new Dog();
2.向下转型,也叫强制转型,只有子类向上转型后才能向下转型
Animal a = new Dog();
Dog dog = (Dog)a;
3.判断是不是向上转型过(子类太多记不清),可以用instanceof判断是不是原类型
package com.itheima.day02.teacher.duotai02;
public class Demo03 {
// 演示类型转换的问题
public static void main(String[] args) {
Animal a = new Lv();//向上转型
a.load();
a.sleep();
//做转换之前 先判断一下类型
if(a instanceof Cat){//a 原本类型 是猫
//转换成猫对象
Cat c = (Cat) a;
c.catchMouse();
}
if(a instanceof Lv){//a 原本类型 是驴
//转换成驴对象
Lv lv = (Lv) a;
lv.laMo();
}
//判断是不是原类型,一般用在多个子类不容易判断中,
//这种是jdk14的新特性,判断时进行转换
if (a instanceof Cat cat){
cat.catchMouse();
}
// Cat c = (Cat) a;//语法是对的
// // ClassCastException 类型转换异常 在开发中要避免
//
// // a 本质是 驴 对象
// // 硬给转成猫
// c.catchMouse();
}
}