2017-05-30 117 views
-1

我是學生,學習Java。我知道,protected表示從childrenthe same package訪問。這裏我們繼承並重寫一個受保護的方法。在這樣一個動作之後,無論基類想調用它自己的方法,它都會從子類中調用新的被覆蓋的方法。我一直在調試這一段時間,並用註釋標記執行順序。但我不明白爲什麼當我從基類構造函數中明確調用基類方法時,它不會調用它?爲什麼從基類調用方法調用子方法?

public class Solution { 

    public static void main(String[] args) { 
     new B(); // first 
    } 

    public static class A { 

     public A() { 
      initialize(); // third 
     } 

     protected void initialize() { 
      System.out.println("class A"); // we never go here 
     } 
    } 

    public static class B extends A { 

     public B() { 
      super(); // second 
      initialize(); // fifth 
     } 

     protected void initialize() { 
      System.out.println("class B"); // fourth, sixth 
     } 
    } 
} 

這是從一個網站上的任務,所以基本的解決方案是將initialize方法的訪問修飾符改變從protectedprivate。但我仍然不明白爲什麼會出現問題。

+0

我認爲這只是調用覆蓋的方法,因爲你是從覆蓋它的類調用超類,所以它總是會使用這個方法從B類? –

+0

這是整個重寫... –

回答

0

作爲達科他回答,根本原因是polymorphism。這意味着我們可以創建子對象,但將它們稱爲它們的父類型,並且當我們調用父層的方法時,我們實際上會引用子對象的方法。

在我的情況下,我創建了一個子對象(標記爲//第一個)B,它有自己的initialize方法的主體。繼承的一個細微差別是它不包含構造函數,所以我可以調用父類的構造函數(標記爲//第二個)。在父類的構造函數中,我調用initialize方法 - 這就是多態,因爲我從其父抽象層調用子方法。

這裏是問題的答案 - 出現這種情況,因爲我們只爲B實例分配的內存,這意味着,我們採取了A作爲我們基地,並開始擴展它(儘管我們可以在裏面覆蓋任何東西)。我們做的只有兩兩件事是:

  1. 我們創建了一個構造函數(這是不包括在基地,如上所述)
  2. 我們覆蓋了initialize方法的代碼。此對象現在丟失了位於基數內的此方法的代碼。

polymorphism這個概念就是這樣設計的,有沒有辦法讓我們訪問這個基地方法,除非我們專門創建一個對象,要麼是A本身或不覆蓋此方法的孩子。

1

你試圖做的是打敗多態的目的。你可以,但你必須專門打電話。給你的方法添加一個布爾值,並調用super.initialize(Boolean)。再一次地,這違背了多態性和擴展類HAS去了解超類。不是非常優雅。

public class Solution { 
    public static void main(String[] args) { 
     new B(); // first 
    } 

    public static class A { 

    public static boolean USE_SUPER = true; 

     public A() { 
      initialize(USE_SUPER); 
     } 

     protected void initialize(boolean unusedHere) { 
      System.out.println("class A"); 
     } 
    } 

    public static class B extends A { 
     public static boolean USE_EXTENDED = false; 

     public B() { 
      super(); 
      initialize(USE_EXTENDED); 
     } 

    protected void initialize(boolean useSuper) { 
     if (useSuper) 
       super.initialize(useSuper); 
     else 
       System.out.println("class B"); 
    } 
} 

    } 
+0

@SamKruglov,如果A.initialize()不同於B.initialize(),爲什麼使用多態?以不同的方式稱呼它A.initializeA()和B.initializeB()。 – Dakoda

+0

哦,是的,我想我明白了。我們只創建了對象B,因此我們只從這個角度有方法。並且來自父項的調用方法僅意味着多態性。謝謝! – Sam