java炒冷饭系列05 使用多态时需要注意的几点

来源:互联网 发布:战斗妖精雪风模型淘宝 编辑:程序博客网 时间:2024/06/03 01:27

缺陷:“覆盖”私有方法

我们试图像下面这样做也是无可厚非的:

public class PrivateOverride {    private void f(){        System.out.println("private.f()");    }    public static void main(String[] args) {        PrivateOverride po = new Derived();        po.f();    }}class Derived extends PrivateOverride{    public void f(){        System.out.println("public.f()");    }}

输出
PrivateOverride.f()
我们所期望的输出是public.f(),但是由于private方法被自动认为是final方法,而且对导出类是屏蔽的。因此,在这种情况下,Derived类中的f()方法就是一个全新的方法;
既然基类中的f()方法在子类Derived中不可见,因此甚至也不被重载。

结论就是:只有非private方法才可以被覆盖;但是还需要密切注意覆盖private方法的现象,这时虽然编译器不会报错,但是也不会按照我们所期望的来执行。确切地说,在导出类中,对于基类中的private方法,最好采用不同的名字。

缺陷:域与静态方法

一旦你了解了多态机制,可能就会开始认为所有事物都可以多态地发生。然而,只有普通的方法调用可以是多态的。例如,如果你直接访问某个域,这个访问将在编译期进行解析,就像下面的示例所演示的

class Super{    public int field = 0;    public int getField(){        return field;    }}class Sub extends Super{    public int field = 1;    public int getField(){        return field;    }    public int getSuperField(){        return super.field;    }}public class FieldAccess {    public static void main(String[] args) {        Super sup = new Sub();        System.out.println("sup.field = " + sup.field + ", sup.getField() = " + sup.getField());        Sub sub = new Sub();        System.out.println("sub.field = " + sub.field + ", sub.getField() = " + sub.getField() + ", sub.getSuperField() = " + sub.getSuperField());    }}

输出
sup.field = 0, sup.getField() = 1
sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0
当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的。在本例中,为Super.fieldSub.field分配了不同的存储空间。这样,Sub实际上包含两个称为field的域:它自己的和它从Super处得到的。然而,在引用Sub中的field时所产生的默认域并非Super版本的field域。因此,为了得到Super.field,必须显式地指明super.field
尽管这看起来好像会成为一个容易令人混淆的问题,但是在实践中,它实际上从来不会发生。首先,你通常会将所有的域都设置成private,因此不能直接访问它们,其副作用是只能调用方法来访问。另外,你可能不会对基类中的域和导出类中的域赋予相同的名字,因为这种做法容易令人混淆。

如果某个方法是静态的,它的行为就不具有多态性

class StaticSuper{    public static String staticGet(){        return "Base staticGet()";    }    public String dynamicGet(){        return "Base dynamicGet()";    }}class StaticSub extends StaticSuper {    public static String staticGet(){        return "Derived staticGet()";    }    public String dynamicGet(){        return "Derived dynamicGet()";    }}public class StaticPolymorphism {    public static void main(String[] args) {        StaticSuper sup = new StaticSub();        System.out.println(sup.staticGet());        System.out.println(sup.dynamicGet());    }}

静态方法是与类,而并非与单个的对象相关联的。

总结

翻了两天书,才找到确切的依据,不容易啊

只有普通的方法调用可以是多态的

参考文献

《Java编程思想》8.2转机