我來繼承窗口類在其他編程環境中,但在Java教程我通常看到類似我應該繼承JFrame/JPanel嗎?
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
p.add(aComponent);
p.add(anotherComponent);
那麼,什麼是Java中關於繼承頂級容器類的約定?
我來繼承窗口類在其他編程環境中,但在Java教程我通常看到類似我應該繼承JFrame/JPanel嗎?
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
p.add(aComponent);
p.add(anotherComponent);
那麼,什麼是Java中關於繼承頂級容器類的約定?
使用的原則,你會爲所有的java類相同。如果您正在修改或擴展行爲或功能,那麼請通過所有方式擴展JPanel
或JFrame
。訣竅是仔細思考並決定是否真的添加任何東西。在大多數的情況下,當我看到人們延伸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
。
通常,當人們擁有包含數據屬性和業務邏輯等的主要應用程序類時,您會發現它們純粹擴展JFrame以便爲其應用程序提供GUI。國際海事組織這是錯誤的,因爲它不是* is-a *,它是* has-a *!如你所說,組成正確的方法。但是,如果您需要*將JFrame/JPanel擴展爲**,爲其添加一些與UI相關的功能**,請不要用這個藉口將所有內容放在一個類中。您應該爲應用程序類提供擴展JFrame的實例,而不是開始將業務邏輯/數據存儲在純粹的UI類中。只是我的0.02美元。 – 2011-09-05 00:38:07
有沒有這個規則,這取決於你如何看待你的對象。你可能有一個具有特定佈局和行爲的JPanel,所以它的例如一個VideoViewerPanel。但即使這個VideoViewerPanel可能包含一個JPanel,它只是用來安排一些按鈕,所以你不會明確地命名它並將它用作JPanel。
我認爲這與Liskov替代原理有關,您應該仔細研究一下 。
一個衆所周知的好做法是避免將頂級容器進行子類化(JFrame
,JDialog
,JInternalFrame
)。
關於JPanel
,幾種做法都在使用:
JPanel
我通常使用第一個選項,這對我來說似乎更符合邏輯,但我也有時使用第二種方式,適應某種程度:我的視圖構建器實際上創建並存儲(作爲字段)所有組件,他們到現有的面板(作爲參數傳遞)。例如,我使用它來重新使用一組組件:例如,我使用它來重用一組組件。我有一個AddressView
類的作品就像那樣,我把它加兩次到ContactView
那個小類JPanel
,一次爲家庭地址,一次爲辦公室地址。
有人可能會說,我也可以爲AddressView
子類JPanel
,然後將2個實例添加到我的ContactView
面板。我不這樣做的原因是因爲Swing LayoutManager
s不支持在不同面板之間對齊組件,因此在這種情況下得到的ContactView面板在視覺上並不令人滿意。
我的一般經驗法則:使用繼承之前,請考慮組合是否更有意義。
原因:子類化通常意味着更多的複雜性和連通性,即難以改變,維護和擴展而不會犯錯誤。
更加完整和具體太陽answer from Tim Boudreau:
到使用繼承的常見問題,因爲我看到它是:
- 無辜的行爲可以有意想不到的效果 - 的這是一個典型的例子,在子類實例字段初始化爲 之前,調用來自超類 構造函數的可重寫方法。在一個完美的世界裏,沒有人會這樣做。這是 不是一個完美的世界。
- 它提供了不正當的誘惑,使得子類人員能夠對方法調用的順序做出假設,例如 - 如果超類隨着時間的推移而變化,這種假設往往不穩定。另見my toaster and coffee pot analogy。
- 類越來越重 - 您不一定知道您的超類在構造函數中正在做什麼,或者使用了多少內存 。因此,構建一些天真的想成爲輕量級的對象可以 遠遠比你想象的更貴,而如果 超進化
- 它鼓勵子類的爆炸,這可能隨時間而改變。課堂上課需要花費時間,更多班級需要記憶。這可能是一個非問題,直到您處理NetBeans規模的應用程序 ,但在那裏,我們遇到了實際的 問題,例如,由於菜單的第一個顯示屏 觸發了大量類加載。我們通過移動到 更多的聲明性語法和其他技術來解決這個問題,但是修復的時間也是 。
- 它使以後難以改變的東西 - 如果您已經創建了一個類,那麼交換超類將會破壞子類 - 這是一種選擇,一旦您將代碼公開化,您就可以結婚 到。因此,如果您沒有改變超類的實際功能,那麼如果您使用 ,則可以更自由地進行更改,而不是擴展所需的功能。舉例來說, 繼承JPanel - 這通常是錯誤的;如果子類是 某處公開,則永遠不會有機會重新審視該決定。如果 以JComponent getThePanel()的形式訪問,您仍然可以執行此操作(提示: 公開您的API中的組件的模型)。
- 對象層次結構不能縮放(或使它們縮放比提前規劃困難得多) - 這是經典的「太多層」 問題。我將在下面討論這個問題,以及AskTheOracle模式如何解決它(儘管它可能會冒犯OOP純粹主義者)。
...
我就做什麼,如果你允許繼承,您可能 採取與一粒鹽的看法是:
- 展露領域,永遠除了常量
- 方法應是抽象的或最終
- 呼叫沒有從父類的構造方法
...
所有適用少的小項目比大,且小於 到私有類公立
這個問題是相似的,我應該使用匿名類或者我應該命名它們 - >沒有對錯。 – rurouni 2011-05-05 09:25:14