eric-1001c

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  3 随笔 :: 45 文章 :: 12 评论 :: 0 Trackbacks

1)利用多态实现向上转型upcase中的方法和域问题

  1. 一般的多态中的方法

 

class Super {
    
public void sayHello(){
        System.out.println(
"Super.sayHello()");
    }

    
public void display(){
        System.out.println(
"Super.display()");
    }

}

class Sub extends Super {
    
public void sayHello(){
        System.out.println(
"Sub.sayHell0()");
    }

    
public void display(){
        System.out.println(
"Sub.display()");
    }

}

public class ExtendsTest {
    
public static void main(String[] args) {
        System.out.println(
"*****Super: Super*****");
        Super sup 
= new Super();
        sup.sayHello();
        sup.display();
        
        System.out.println(
"*****Sub:Sub*****");
        Sub sub 
= new Sub();
        sub.sayHello();
        sub.display();
                
        System.out.println(
"*****Super:Sub*****");
        Super sup2 
= new Sub();
        sup2.sayHello();
        sup2.display();
    }

}

//output
*****Super: Super*****
Super.sayHello()
Super.display()
*****Sub:Sub*****
Sub.sayHell0()
Sub.display()
*****Super:Sub*****
Sub.sayHell0()
Sub.display()

这是最简单,最常见的多态的一种情形,方法是用public修饰的。导出类的方法覆盖了基类的方法,当导出类向上转型的后(sub-->super),sup2在加载类方法的时候,会检查导出类是否有覆盖该方法,如果有就调用导出类的方法,因此这里sup2.display(),sup2.sayHello()结果都是Sub的。在这种情况下最好是使用javase5的@Override注解.但如果基类的方法是private(也就是final),那又会出现什么情况呢?

class Sub extends Super {
    @Override
    
public void sayHello(){
        System.out.println(
"Sub.sayHell0()");
    }

    @Override
    
public void display(){
        System.out.println(
"Sub.display()");
    }

}

public class Super {
    
public void sayHello(){
        System.out.println(
"Super.sayHello()");
    }

    
public void display(){
        System.out.println(
"Super.display()");
    }

    
private void sayGoodbye(){
        System.out.println(
"Super.sayGoodbye()");
    }

    
public static void main(String[] args) {
        System.out.println(
"*****Super: Super*****");
        Super sup 
= new Super();
        sup.sayHello();
        sup.display();
        sup.sayGoodbye();
        
        System.out.println(
"*****Sub:Sub*****");
        Sub sub 
= new Sub();
        sub.sayHello();
        sub.display();
//        sub.sayGoodbye();   sub class cann't invoke the private method of superclass 
                
        System.out.println(
"*****Super:Sub*****");
        Super sup2 
= new Sub();
        sup2.sayHello();
        sup2.display();
            // inoke the mothd of super class
        sup2.sayGoodbye();
    }

}

在这个例子中,主要是想体现出如果基类的方法是private的,导出类就不能继承这个方法。在向上转型中调用这个方法,能且仅能调用基类的private方法(当然要求main()在基类中调用,否则在基类以外的地方不能调用基类的private方法,这个列子正是如此)
下面再看如果方法是static的呢

class StaticSuper{
    
public static void staticGet(){
        System.out.println(
"staticsuper.staticGet()");
    }

    
public void dynamicGet(){
        System.out.println(
"staticsuper.dynamicGet()");
    }

}

class StaticSub extends StaticSuper{
    
public static void staticGet(){
        System.out.println(
"staticsub.staticGet()");
    }

    
public void dynamicGet(){
        System.out.println(
"staticsub.dynamicGet()");
    }

}

public class StaticPolymorphism {
    
public static void main(String[] args) {
        StaticSuper sup 
= new StaticSub();
        sup.staticGet();
        sup.dynamicGet();
    }


}

//output
staticsuper.staticGet()
staticsub.dynamicGet()

由这个例子可以知道在多态是不适用于static的方法的。也就是说在加载类的时候,编译器调用static方法不会去检查导出类是否对基类的static方法是否覆盖,而是直接装载基类的static方法。

2)多态中的域

class FieldSuper{
    
public int field =0;
    
public int getField(){
        
return field;
    }

}

class FieldSub extends FieldSuper{
    
public int field =1;
    
public int getField(){
        
return field;
    }

    
public int getSuperField(){
        
return super.field;
    }

}

public class FiledPolymorphism {
    
public static void main(String[] args) {
        FieldSuper sup 
= new FieldSub();//upcast
        System.out.println("sup.field= "+ sup.field+
                
", sup.getField()"+sup.getField());
        
        FieldSub sub 
= new FieldSub();
        System.out.println(
"sub.field()= "+
                sub.field
+ ", sub.getfield()= "+
                sub.getField()
+",sub.getSuperField() = "+
                sub.getSuperField());
    }

}
//output
sup.field= 0, sup.getField()1
sub.field()= 1, sub.getfield()= 1,sub.getSuperField() = 0

域在多态中是不会被覆盖的,FielddSuper.field和FieldSub.field被分配了两个不同的存储空间,同时在向上转型的时候,编译器也不会向下去找导出类是否覆盖类的域,因此sup.field()返回了FieldSuper的field而不是FieldSub的field。对于想在导出类中获得基类的域,就得像例子那样通过super方法来获取

总结:对于利用多态的向上转型,编译器先从向上转型后的基类出发,找出要调用的元素。根据不同元素采取不同的策略,如果是域,static以及private的方法,则不会去检查导出类是否覆盖这些方法(其实是不能覆盖的)而直接调用基类的;如果是public的方法则检查导出类是否覆盖,覆盖了就会调用导出类的,否则调用基类的

 

posted on 2007-07-11 13:53 Eric-1001c 阅读(170) 评论(0)  编辑  收藏 所属分类: ThinkingInJava

只有注册用户登录后才能发表评论。


网站导航: