2011-05-05 78 views
6

我來繼承窗口類在其他編程環境中,但在Java教程我通常看到類似我應該繼承JFrame/JPanel嗎?

JPanel p = new JPanel(); 
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); 

p.add(aComponent); 
p.add(anotherComponent); 

那麼,什麼是Java中關於繼承頂級容器類的約定?

+1

這個問題是相似的,我應該使用匿名類或者我應該命名它們 - >沒有對錯。 – rurouni 2011-05-05 09:25:14

回答

6

使用的原則,你會爲所有的java類相同。如果您正在修改或擴展行爲或功能,那麼請通過所有方式擴展JPanelJFrame。訣竅是仔細思考並決定是否真的添加任何東西。在大多數的情況下,當我看到人們延伸JFrame這是不必要的和錯誤的;

public class MyFrame extends JFrame { 
    public static void main(String[] args) { 
    new MyFrame().setVisible(true); 
    } 
} 

爲什麼要麻煩延長JFrame?你還沒有添加任何東西!構圖是一個更好的選擇。

擴展JPanel有點不同。 JPanel是一個相當抽象的概念,它只是其他組件的通用容器。恕我直言,JPanel的子類是有效的,以創建一個更具體的面板,然後在你的應用程序中使用它。它促進了OOP和封裝。

例如,您的GUI有2個主顯示區域;一個帶有一些按鈕/控制/輸入,另一個顯示輸出(例如在文本區域)。子類JPanel創建一個包含按鈕/控件/輸入的ControlPanel是完全可以接受的。這將所有代碼移動到一個漂亮的整潔模塊中,清理包含並處理主要文件的類JFrame

+0

通常,當人們擁有包含數據屬性和業務邏輯等的主要應用程序類時,您會發現它們純粹擴展JFrame以便爲其應用程序提供GUI。國際海事組織這是錯誤的,因爲它不是* is-a *,它是* has-a *!如你所說,組成正確的方法。但是,如果您需要*將JFrame/JPanel擴展爲**,爲其添加一些與UI相關的功能**,請不要用這個藉口將所有內容放在一個類中。您應該爲應用程序類提供擴展JFrame的實例,而不是開始將業務邏輯/數據存儲在純粹的UI類中。只是我的0.02美元。 – 2011-09-05 00:38:07

3

有沒有這個規則,這取決於你如何看待你的對象。你可能有一個具有特定佈局和行爲的JPanel,所以它的例如一個VideoViewerPanel。但即使這個VideoViewerPanel可能包含一個JPanel,它只是用來安排一些按鈕,所以你不會明確地命名它並將它用作JPanel。

1

一個衆所周知的好做法是避免將頂級容器進行子類化(JFrame,JDialog,JInternalFrame)。

關於JPanel,幾種做法都在使用:

  • 子類,它爲每一個視圖(再加入 所有組件的子類 構造函數中)
  • 創建ViewBuilder(每樣 的查看)動態地將 組件添加到「標準」JPanel

我通常使用第一個選項,這對我來說似乎更符合邏輯,但我也有時使用第二種方式,適應某種程度:我的視圖構建器實際上創建並存儲(作爲字段)所有組件,他們到現有的面板(作爲參數傳遞)。例如,我使用它來重新使用一組組件:例如,我使用它來重用一組組件。我有一個AddressView類的作品就像那樣,我把它加兩次到ContactView那個小類JPanel,一次爲家庭地址,一次爲辦公室地址

有人可能會說,我也可以爲AddressView子類JPanel,然後將2個實例添加到我的ContactView面板。我不這樣做的原因是因爲Swing LayoutManager s不支持在不同面板之間對齊組件,因此在這種情況下得到的ContactView面板在視覺上並不令人滿意。

1

我的一般經驗法則:使用繼承之前,請考慮組合是否更有意義。

原因:子類化通常意味着更多的複雜性和連通性,即難以改變,維護和擴展而不會犯錯誤。

更加完整和具體太陽answer from Tim Boudreau

到使用繼承的常見問題,因爲我看到它是:

  • 無辜的行爲可以有意想不到的效果 - 的這是一個典型的例子,在子類實例字段初始化爲 之前,調用來自超類 構造函數的可重寫方法。在一個完美的世界裏,沒有人會這樣做。這是 不是一個完美的世界。
  • 它提供了不正當的誘惑,使得子類人員能夠對方法調用的順序做出假設,例如 - 如果超類隨着時間的推移而變化,這種假設往往不穩定。另見my toaster and coffee pot analogy
  • 類越來越重 - 您不一定知道您的超類在構造函數中正在做什麼,或者使用了多少內存 。因此,構建一些天真的想成爲輕量級的對象可以 遠遠比你想象的更貴,而如果 超進化
  • 它鼓勵子類的爆炸,這可能隨時間而改變。課堂上課需要花費時間,更多班級需要記憶。這可能是一個非問題,直到您處理NetBeans規模的應用程序 ,但在那裏,我們遇到了實際的 問題,例如,由於菜單的第一個顯示屏 觸發了大量類加載。我們通過移動到 更多的聲明性語法和其他技術來解決這個問題,但是修復的時間也是 。
  • 它使以後難以改變的東西 - 如果您已經創建了一個類,那麼交換超類將會破壞子類 - 這是一種選擇,一旦您將代碼公開化,您就可以結婚 到。因此,如果您沒有改變超類的實際功能,那麼如果您使用 ,則可以更自由地進行更改,而不是擴展所需的功能。舉例來說, 繼承JPanel - 這通常是錯誤的;如果子類是 某處公開,則永遠不會有機會重新審視該決定。如果 以JComponent getThePanel()的形式訪問,您仍然可以執行此操作(提示: 公開您的API中的組件的模型)。
  • 對象層次結構不能縮放(或使它們縮放比提前規劃困難得多) - 這是經典的「太多層」 問題。我將在下面討論這個問題,以及AskTheOracle模式如何解決它(儘管它可能會冒犯OOP純粹主義者)。

...

我就做什麼,如果你允許繼承,您可能 採取與一粒鹽的看法是:

  • 展露領域,永遠除了常量
  • 方法應是抽象的或最終
  • 呼叫沒有從父類的構造方法

...

所有適用少的小項目比大,且小於 到私有類公立