今天的博客主题
基础篇 --》面向对象 --》Java多态
什么是多态?
多态就是同一个行为具有了多个不同表现形式或行太的能力。
多态性是对象多种表现形式的体现。
举个例子:
键盘上的F1按钮,在不同的软件上按F1出现的结果是不同的
就是在同一事件发生在不同的对象上既产生不同的结果
有点抽象比较难理解哈,看后面的解释就明白了。
多态的优点
消除类型之间的耦合性
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
态存在的三个要素
- 继承
- 重写
- 父类引用指向子类对象
多态可以是方法多态,也可以是对象多态。
那方法的多态性是什么呢?
方法的重写重载被称为多态。
对象的多态性是什么呢?
对象的多态是发生在继承关系当中的,子类和父类之间的转换
代码理解
例
public class Person {
public void money(){
System.out.println("钱?");
}
}
public class Man extends Person{
@Override
public void money(){
System.out.println("男人挣钱");
}
}
public class Woman extends Person {
@Override
public void money(){
System.out.println("女人挣钱");
}
}
public class TestDemo {
public static void main(String[] args) {
//实例化Person
Person p = new Person();
p.money();
//实例化Man
Person pm = new Man();
pm.money();
//实例化Woman
Person pw = new Woman();
pw.money();
}
}
输出结果:
钱?
男人挣钱
女人挣钱
看完这段代码是不是觉得没什么,实际上已经实现了多态
方法的多态就是Man Woman子类对Person类里的方法进行重写。
这两行代码就实现了对象的多态性
Person pm = new Man();
Person pw = new Woman();
这个也就是对象多态性里的向上转型是自动完成的,所有的子类都可以自动向上转型成父类。
有向上转型可能也会有向下转型
结合上面的例子向下转型就是:Woman woman = (Woman) pw;这样就实现了向下转型
这种转型需要在实际的业务逻辑当中根据需求来实现。
这样满足了多态的三要素:继承了,重写了、父类的引用指向了子类对象
在改造下:
public class TestDemo {
public static void main(String[] args) {
//实例化Person
Person p = new Person();
getMoney(p);
//实例化Man
Person pm = new Man();
getMoney(pm);
//实例化Woman
Person pw = new Woman();
getMoney(pw);
}
public static void getMoney(Person p){
p.money();
}
}
这样是不是也体现出来了在同一事件发生在不同的对象上也就产生不同的结果。
当使用多态方式调用方法时,首先会检查父类中有么有这个方法,如没有那就直接编译错误。
如果有在去调用子类的同名方法(这里不能是static方法,static方法只能继承,不能重写)
子类重写父类方法,只对父类的同名方法起到了隐藏作用,当调用的时候用谁的引用,则调用谁的方法。
总结
继承是多态得以实现的基础。
从字面上理解,多态就是一种类型(都是Person类型)表现出来的多种状态(男人,挣钱;女人,花钱)
将一个方法调用同这个方法所属的主题(也就是对象或类)关联起来叫做绑定。
绑定分为:前期绑定和后期绑定。
1.前期绑定:在程序运行之前进行绑定,由编译器和连接程序实现,又叫做静态绑定。比如static方法和final方法。注意,这里也包括private方法,因为他是隐式final的。
2.后期绑定:在运行时根据对象的类型进行绑定。由调用机制实现,因此又叫做动态绑定,或运行时绑定。除了前期绑定之外的所有方法都属于后期绑定。
也被称之为动态多态(运行时多态)。
经典多态例题:
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)
思而不学则殆