多态
多态字面意思来看,是多种状态。
在Java中多态就是接口的多种不同实现方式。允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
简单说多态就是对象多种表现形式的体现。
多态的优点
1)解除类型间的耦合性
2)可替换性
3)可扩展性
4)灵活性
5)接口性
6)简化性
多态的三个必要条件
1)有继承
2)有重写
3)父类引用指向子类对象
多态的分类
多态有方法多态和对象多态
方法的多态
方法的多态性就是方法的重写重载
1)方法的重写:同一个方法,根据子类的不同,实现的功能不同
2)方法的重载:同一个方法名,根据传入的参数类型及个数不同执行不同的方法体
对象的多态
对象的多态发生发生在继承关系中,子类与父类之间转换的问题。
1)向上转型:子类转父类(自动完成)左边父类,右边子类
2)向下转型:父类转子类(强制完成)左边子类,右边父类
// 人类 作为一个顶级父类,可以扩展人类所有的工作职业
public class Person {
public void work(String work){
System.out.println(" 人类 " + work);
}
}
// 老师类 继承 人类
public class Teacher extends Person {
public void work(String work){
System.out.println(" 老师类 " + work);
}
}
// 学生类 继承 人类
public class Student extends Person {
public void work(String work){
System.out.println(" 学生类 " + work);
}
}
// 警察类,医生类等等 都可以继承 人类
// 测试
public static void main(String[] args) {
Person p = new Student();
p.work("听课");
p = new Teacher();
p.work("讲课");
TestPolys(new Student(),"s 听课");
TestPolys(new Teacher(),"t 讲课");
}
public static void TestPolys(Person p, String work){
p.work(work);
}
// 输出结果
学生类 听课
老师类 讲课
学生类 s 听课
老师类 t 讲课
按照上面描述我们实现一个多态,但是如果想深入了解多态,还需要了解一下绑定。
将一个方法调用与一个方法主体关联起来被称作绑定。
在程序执行前进行绑定(如果有的话,由编译器和连接程序实现)叫做前期绑定。
有前期绑定就有后期绑定,俩在一起可能会做个互补什么的。
后期绑定就是程序在运行时根据对象的类型进行绑定。
后期绑定也叫做,运行时绑定、动态绑定。
如果想要实现后期绑定,那就具备一种机制,以便程序在运行时能判断对象的类型,从而调用合适的方法。
Java中除了static方法和final方法之前,所有的方法都是后期绑定。
方法声明为final,那就是想不让其他类来覆盖该方法,也可以说是在关闭动态绑定。
静态方法的行为不具备多态性。
静态方法是与类相关联的,并不是与单个的对象所关联。
注意:
1)如果子父类存在同名的成员变量时,访问的是父类的成员变量。
2)如果子父类存在同名的非静态方法时,访问的是子类的方法。
3)如果子父类存在同名的静态方法时,访问的是父类的方法。
多态经典题
class A {
public String show(D obj){
return ("A and D");
}
public String show(A obj){
return ("A and A");
}
}
class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
class C extends B {}
class D extends B {}
// 以下输出结果是什么???
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println(a1.show(b));
System.out.println(a1.show(c));
System.out.println(a1.show(d));
System.out.println(a2.show(b));
System.out.println(a2.show(c));
System.out.println(a2.show(d));
System.out.println(b.show(b));
System.out.println(b.show(c));
System.out.println(b.show(d));
// 输出结果
A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D
分析:
1)实例对象为A,参数为对象B,B为A的子类。执行A.class中show(A obj)
2)同上
3)实例对象为A,参数为对象D,执行A.class中show(D obj)
4)实例对象为A,参数为B,本应执行A.class中show(A obj),但是,B.class重写了show(A obj),所以执行B.class show(A obj)
5)同上
6)执行A.class show(D obj) B中并没有重写。
7)实例对象为B,参数为B或者B的子类,执行show(B obj)
8)实例对象为B,参数为B或者B的子类,执行show(B obj)
9)实例对象为B,参数为D,因为B继承自A,也可以执行A中的show(D obj)