多态的一般形式Father f = new Son()。通过以下这个例子来说明多态的各个知识点,如果能完全弄明白,就掌握的差不多了。
一,向上转型的对象有以下特点,看以下代码
public class PolyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Poly p = new Son( 1 );
p.s = 0 ;
p.p3();
p.p2();
// p.s1 = 0;子类的新增变量不可用
}
}
class Poly{
int s;
void p1(){
p3();
}
static void p2(){
System.out.println( " Poly " );
}
void p3(){
System.out.println( " Poly " );
}
Poly( int i){
}
}
class Son extends Poly{
int s1;
Son( int i) {
super (i);
}
// Son(int i) {
// }必须要super继承父类
// Son(){}父类没有的构造方法不能写
static void p2(){
System.out.println( " Son " );
}
void p3(){
System.out.println( " Son " );
}
// void p2(){
// System.out.println("Son");
// }static类型也要一致
} /** Output
*Son
*Poly
*/
1,向上转型的对象不能操作子类的新增成员变量,不能使用子类的新增方法。
2,可以操作子类继承或者隐藏的成员变量,也可以使用子类继承或重写的方法。
3,一定是调用重写的方法。
二,子类覆盖的方法权限一定不能比基类小
权限按大小排列为:public protected friendly(默认) private。
如果基类是final型(private默认是final型)方法,则子类重写的方法为新方法,与父类为两个方法。
三,域与static方法
当对象向上转型为引用时,域不存在多态。一般情况域都用private,所以这条没什么意义。
static型方法也不具有多态性。
四,初始化问题
class
Poly2{
void draw(){
System.out.println( " Polydraw " );
}
Poly2(){
System.out.println( " Poly before draw " );
draw();
System.out.println( " Poly after draw " );
}
}
class Son2 extends Poly2{
private int r = 1 ;
void draw(){
System.out.println( " Sondraw.r = " + r);
}
Son2( int r){
this .r = r;
System.out.println( " Son.r = " + r);
}
}
public class PolyTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Poly2 s = new Son2( 5 );
// new Son2();
// Son2 s2 = new Son2();三种初始化情况都一样
}
} /** Output
*Poly before draw
*Sondraw.r = 0
*Poly after draw
*Son.r = 5
*/// ~
void draw(){
System.out.println( " Polydraw " );
}
Poly2(){
System.out.println( " Poly before draw " );
draw();
System.out.println( " Poly after draw " );
}
}
class Son2 extends Poly2{
private int r = 1 ;
void draw(){
System.out.println( " Sondraw.r = " + r);
}
Son2( int r){
this .r = r;
System.out.println( " Son.r = " + r);
}
}
public class PolyTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Poly2 s = new Son2( 5 );
// new Son2();
// Son2 s2 = new Son2();三种初始化情况都一样
}
} /** Output
*Poly before draw
*Sondraw.r = 0
*Poly after draw
*Son.r = 5
*/// ~
由上面的代码可见,初始化过程是这样的
1,所有域初始化为0(boolean值为false)。
2,从基类开始调用构造器。在上面的代码中,基类调用被重写的Son2.draw()方法,并且是在Poly2构造前调用,所以r的值是0。
3,按申明顺序调用成员的初始化方法。
4,导出构造器的主体。