目录
一、多态的表现形式
两种
1.方法的重载和重写
2.对象的多态性(向上转型和向下转型)
二、重载和重写的简单介绍
1.重载(overload)
1)在同一个类中
2)有两个或两个以上重名的方法
3)但是方法的参数个数、类型、顺序至少有一个不一样
2.重写(override)
1)发生在继承关系当中,子类对父类的方法进行的重新定义
2)子类中的某些方法与父类中的某些方法,方法名,参数列表完全一致,即使方法体内部没有改变,或者是空方法体也是重写
三、向上转型和向下转型的简单介绍
1.向上转型
子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口。
Father f=new Son(); //向上转型
2.向下转型
向下转型是把父类对象转为子类对象。
Animal a=new Animal();
Dog g=(Dog)a; //向下转型
四、在多态中方法的调用机制
1.不发生继承的类调用方法时,调用哪个就用哪个,如果发生了重载,那么,可以根据参数个数,类型,顺序判断到底调用了哪一个方法
2.当发生了继承关系,但是没有向上,向下转型时,子类对象调用的方法,要么是自身独有的,要么就是自身重写的,如果没有重写,那么也会直接调用父类的方法;而父类对象则只能调用自身的方法,而无法使用子类的方法。
3.如果发生了继承,并且有向上转型的对象,那就秉承着一个原则,即:编译看左边,运行看右边。
也就是说,首先看父类中这个被调用的方法在哪里,当父类中存在这个方法时,才可以调用,并且要继续看子类中是否重写了该方法,如果重写了,就调用重写后的方法。
总结:
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
this.show(O)本类中是否有该方法
super.show(O)本类的父类中是否有该方法
this.show((super)O)本类中是否有参数父类的方法(即现在参数的父类类型作为参数的方法)
super.show((super)O)本类的父类中是否有参数父类的方法
五、实例的分析
package test;
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 {
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
a1.show(b);//"A and A"
System.out.println(a1.show(b));//A and A
a1.show(c);//"A and A"
System.out.println(a1.show(c));//a and A
a1.show(d);//"A and D"
System.out.println(a1.show(d));//A and D
a2.show(b);//"B and B"错了
System.out.println(a2.show(b));//B and A
a2.show(c);//"B and B"错了
System.out.println(a2.show(c));//B and A
a2.show(d);//"A and D
System.out.println(a2.show(d));//A and D
b.show(b);//"B and B"
System.out.println(b.show(b));//B and B
b.show(c);//"B and B"
System.out.println(b.show(c));//B and B
b.show(d);//"A and D"
System.out.println(b.show(d));//A and D
}
}
注释的部分分别是我猜测的答案和真是输出的答案。
下面分块说明
1.继承关系
A是B的父类,B是C和D的父类
并且C,D没有重写B的任何方法,也没有自身的方法
B对A进行了方法的重写show(A obj)
单独看B,它的两个show方法就属于重载
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 {
}
2.new对象的分析
由于调用方法只用到了这三个对象,因此只看这三个。
a1单纯的A对象
a2发生了向上转型,A引用B的对象
b单纯的B对象
A a1 = new A();
A a2 = new B();
B b = new B();
3.对于方法的调用
1)a1对象调用,以a1.show(b)为例,首先A中并没有show(B obj)的方法,A继承于Object类,其中也没有show(B obj)。
那么由于B继承于A,看A中是否有show(A obj),好的,有,那么就调用该方法,输出“A and A”
System.out.println(a1.show(b));//A and A
System.out.println(a1.show(c));//A and A
System.out.println(a1.show(d));//A and D
2)a2对象调用,以a2.show(b)为例,因为是向上转型,那么遵循,编译看左,运行看右的原则,在父类A中没有show(B obj)方法,但同样的有show(A obj),因此要调用该方法;又因为在B中重写了A中的show(A obj),因此在调用的时候就调用了子类重写的show(A obj),输出“B and A”
System.out.println(a2.show(b));//B and A
System.out.println(a2.show(c));//B and A
System.out.println(a2.show(d));//A and D
3)b对象调用,以b.show(b)为例,在B中恰好就有show(B obj)的方法,因此就输出"B and B"
System.out.println(b.show(b));//B and B
System.out.println(b.show(c));//B and B
System.out.println(b.show(d));//A and D