1.多态的格式
Shape s = new Circle();</span>
多态实际上相当于向上转型,它能够传入一个参数列表为父类的函数,是因为,子类时父类的一种,所以可以传进去
2.方法绑定
绑定:将一个方法调用同一个方法主体关联起来被称为绑定
前期绑定:编译时期将各自对应关系绑定不变,如static,final(private属于final)修饰的方法
后期绑定:在运行时根据对象的类型进行绑定,除了static,fiinal(private属于final)修饰的方法之外都是后期绑定
3.Shape s = new Circle();中,创建了一个Circle对象,并把得到的引用复制给Shape,因为Circle是通过继承Shape得到的,所以Circle是Shape的一种
4.多态时,成员的特点
(1)成员变量
编译时:参考引用变量所属类(父类)中是否有调用的成员变量,如果没有编译失败
运行时:参考引用变量所属类(父类)中是否有调用的成员变量,并执行父类中的成员变量
总结:编译时,运行时都看左边的父类是否有这个变量,并执行父类中变量的值
例:
class Fu{
int num = 1;
}
class Zi extends Fu{
int num = 2;
}
class Test{
public static void main(String[] args){
Fu obj = new Zi();
syso("num = " + num);
}
}
//输出结果: num = 1
(2)成员函数
编译时:参考引用变量所属类是否有调用的函数,如果没有则编译失败
运行时:参考对象所属类(子类)中是否有调用的函数,如果子类中没有覆盖的函数就调用父类的函数,如果子类中有覆盖的函数,调用子类的。
总结:编译时看左边,运行时看右边,右边不行再看左边
class Fu{
void show(){ syso( "Fu show" )}
}
class Zi extends Fu{
void show(){ syso ( " Zi show "))}
}
主函数中:
Fu obj = new Zi()
obj.show()
输出结果: Zi show
(3)静态函数:静态函数不具有多态性
原因:静态函数调用只与其所属类有关,不需要对象调用,因而只与引用有关,而多态时指对象的
总结:编译运行均看所属类(父类)是否有调用的函数
5.构造器与多态
构造器并不具有多态(他们实际上是static方法,只不过static声明是隐式的),但有必要理解构造器怎样通过多态在复杂的层次结构中运作。
(1)构造器的调用顺序
(i)调用基类构造器(不断的递归,知道遇到这个结构的根节点,最老最老的父节点),然后再逐步向外层调用构造器
(ii)按声明顺序调用成员的初始化方法
(iii)调用导出类构造器的主体
(2)继承与处理
假设父类中有一个清理不用的对象的方法dispose(),子类覆盖了。当覆盖被继承类的dispose()方法时一定要记得,在子类的dispose()方法调用基类的disose()方法,否则基类的清理动作就不会发生
如果有多重的继承关系,销毁的顺序也比较重要。如果某一子类依赖于其他多重基类,销毁的顺序应该与初始化的顺序想法。对于字段,则意味着与声明顺序相反(因为字段的初始化是按照声明的顺序进行的)。对于基类调用了子类时,应该首相对子类进行处理,然后才是基类,这是因为子类处理可能会调用街垒中的方法,所以不宜过早的消除基类对象。(一句话:反着来,别导致现在想用的被处理了,到时候就尴尬了。。。)
6.协变返回类型
javaSE5中添加类协变返回类型,它表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类型(一句话,子类覆盖父类的方法时,以前覆盖是包括返回类型,函数名,参数等一模一样,现在返回类型可以是父类返回类型的子类了。)
7.一旦用了多态,导出类中扩展的内容就不能被基类访问,因此一旦向上转型,就不能调用那些新的方法
如果非得想调用导出类特有的内容,就得在多态基础上,再向下转型 Fu obj1 = new Zi(),coding......,Zi obj2 = (Zi)obj1;