Java-多态

在以前 对多态的理解就只停留在 重载 和 重写 其实多态还有很多方面的知识
我们先举一个多态的最典型的运用

1
2
3
4
// 假设我们有一个父类person   两个子类student teacher
Person a=new Student();
Person b=new Teacher();

上面两个对象的创建都是正确的 但是a 和 b 和正常的子类又有一些不同

多态有什么典型的运用场景?


其实很简单 假如有一个场景 用户注册的页面 假如一共有三种对象 老师 学生 管理员

那么我们的注册函数传入的对象参数填什么呢? Stuent? Teacher? Admin? 这个时候没有多态的话,我们就要单独创建出三个注册函数 分别传三个对象 但是有了多态就可以用父类作为参数

1
2
3
4
public static register(Person p){
//注册函数
//此时调用函数时 参数无论时学生老师还是管理员都可以成功调用
}

什么是多态?


同类型的对象 表现出的不同形态

多态的表现形式


父类类型 对象名称 = 子类对象

Peron p =new Stuent()

多态的前提


  • 有继承关系
  • 有父类引用指向子类对象 Person p = new Stuent();
  • 有方法重写

多态调用成员的特点


  • 变量的调用 : 编译看左边 运行也看左边
  • 方法的调用 : 编译看左边 运行看右边

这个很重要 一定要仔细理解

1.成员方法:动态绑定(看右边)
  • 编译期:编译器检查左边的引用类型 如果父类没有这个方法 编译报错
  • 运行期:程序观察右边的实际对象 如果子类重写了该方法 则执行子类的方法
2.成员变量:静态绑定(看左边)
  • 编译器:编译器检查左边的引用类型
  • 运行期:依然访问做 “左边”引用类型的变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public Person{
int num=10;
void show(){
sout("父类方法")
}
}

public Stuent extends Person{
int num=20;

@Override
void show(){
sout("子类的方法")
}
}

public class Test {
public static void main(String[] args) {
// 多态向上转型
Parent obj = new Child();

// 1. 调用方法:看右边 (Child)
obj.show();
// 输出:子类重写的方法

// 2. 调用变量:看左边 (Parent)
System.out.println("num 的值是:" + obj.num);
// 输出:num 的值是:10
}
}

多态的优势


  • 在多态的形式下 右边的对象可以实现解耦合 便于扩建和维护

    1
    2
    Person p =new Student()
    p.work() //后续不想让学生工作 只用该前面的部分代码
  • 定义方法的时候 使用父类类型作为参数 可以接受所有子类对象 体现多态的扩展性和便利

多态的弊端


毕竟你用的时父类的类型创建对象 子类的所有功能并不能完全实现

  • 不能调用子类的特有功能 (父类中没有 子类中没有重写 特有的成员方法)

    解决方案:利用强制类型转换即可

这里讲一个实际场景 假如已经进入注册函数界面了 然后你想调用子类特有的方法 就嘚强制类型转化一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void register(Person p){
//注册函数


//常见的转换模板
if(p instanceof Stuent stu){
//此时stu就是一个正常的Student对象
}else if(p instanceof Teacher teacher){

}else if(p instanceof Admin admin){

}else{
sout("没有这个类型 转换失败")
}
}