java當心機(6)| 多態的一些坑

對於"多態"的概念,想必你們都很熟悉了,但咱們仍是來回顧一下吧

class Actor {
    public void act(){
        System.out.println("Actor");
    }
}

class HappyActor extends Actor{
    @Override
    public void act() {
        System.out.println("HappyActor");
    }
}

class SadActor extends Actor{
    @Override
    public void act() {
        System.out.println("SadActor");
    }
}

public class Test {
    public static void main(String[] args) {
        Actor hActor = new HappyActor();//向上轉型
        Actor sActor = new SadActor();//向上轉型
        hActor.act();
        sActor.act();
    }
}
//out:
HappyActor
SadActor

上面例子中,HappyActor和SadActor都繼承Actor並重寫了act方法,在main函數中,兩個Actor對象調用相同方法產生不一樣的結果,就稱爲"多態"。app


在設計程序中,"多態"可以使代碼變得靈活,有時候仍是很好使得,但也有一些坑在裏面,下面就給你一一道來ide


坑1 "覆蓋"私有方法
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()");
    }
}
//out:
private f()

咱們指望輸出的是public f(),但結果並不是咱們所想。PrivateOverride中的f()方法是私有的,對它的子類是不可見的,Derived 的f()方法沒法覆蓋它。

函數

結論:沒法覆蓋私有方法。須要注意,子類中方法切勿與父類中的私有方法同名,不然會容易混淆。spa


坑2 域與靜態方法不存在多態
1. 域
class SuperClass {
    public String field = "Super field";

    public String getField() {
        return field;
    }
}

class SubClass extends SuperClass {
    public String field = "Sub field";

    @Override
    public String getField() {
        return field;
    }

    public String getSuperField() {
        return super.getField();
    }
}

public class FieldAccess {
    public static void main(String[] args) {
        SuperClass sup = new SubClass();//向上轉型
        System.out.println("sup.field = " + sup.field
                + ", sup.getField() = " + sup.getField());

        SubClass sub = new SubClass();
        System.out.println("sub.field = " + sub.field
                + ", sub.getField() = " + sub.getField()
                +", sub.getSuperField() = " + sub.getSuperField());
    }
}
//out:
sup.field = Super field, sup.getField() = Sub field
sub.field = Sub field, sub.getField() = Sub field, 
sub.getSuperField() = Super field

域的訪問操做是由編譯器解析的,因此不是多態的。(擴展:多態是由動態綁定實現的,便是在程序運行期對數據作綁定)設計


SuperClass中的field和SubClass中的field分配了不一樣的內存空間,在SubClass中實際上包含了兩個field:一個是本身的和從父類SuperClass中繼承的。子類SubClass中可以使用super.field顯示地指明SuperClass中的field。
code


2. 靜態方法
class StaticSuper{
    public static String staticGet(){
        return "Base staticGet()";
    }

    public  String dynamicGet(){
        return "Base dynamicGet()";
    }
}

class StaticSub extends StaticSuper{
    public static String staticGet(){
        return "Base staticGet()";
    }

    @Override
    public  String dynamicGet(){
        return "Base dynamicGet()";
    }
}
public class StaticMethod {
    public static void main(String[] args) {
        StaticSuper sup = new StaticSub();
        System.out.println(sup.staticGet());
        System.out.println(sup.dynamicGet());
    }
}
//out:
Base staticGet()
Base dynamicGet()

靜態方法沒法被覆蓋,沒法實現多態。
對象


總結:域與靜態方法都沒法實現多態。須要注意,儘量不對父類和子類的域使用相同的名字,沒法覆蓋的方法不使用相同名字,以避免形成混淆。繼承

相關文章
相關標籤/搜索