我习惯于在其他编程环境中对窗口类进行子类化,但在java教程中我经常会看到类似
的内容。JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
p.add(aComponent);
p.add(anotherComponent);
那么Java中有关子类化顶级容器类的约定是什么?
答案 0 :(得分:6)
使用与所有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
的类。
答案 1 :(得分:3)
没有这方面的规则,这取决于你如何看待你的对象。您可能有一个具有特定布局和行为的JPanel,因此它可以是一个VideoViewerPanel。但即使是这个VideoViewerPanel也可能包含一个JPanel,它只是为了安排一些按钮,所以你没有明确地命名它,只是将它用作JPanel。
答案 2 :(得分:2)
我认为这与Liskov替代原则有关, 你应该调查一下。
答案 3 :(得分:1)
一个众所周知的良好做法是避免继承顶级容器(JFrame
,JDialog
,JInternalFrame
)。
关于JPanel
,正在使用几种做法:
JPanel
我通常使用第一个选项,这对我来说似乎更合乎逻辑,但我有时也会使用第二种方式,适应水平:我的视图构建器实际上创建并存储(作为字段)所有组件但是将它们添加到现有面板(作为参数传递)。
例如,我使用它来重用组件集:例如我有一个类似的AddressView
类,我将它添加到ContactView
的子类JPanel
,一次添加到家庭地址,一次添加到办公地址。
可以说我也可以为JPanel
创建AddressView
的子类,然后将2个实例添加到ContactView
面板中。我不这样做的原因是因为Swing LayoutManager
不支持跨不同面板对齐组件,因此在这种情况下生成的ContactView面板在视觉上并不令人满意。
答案 4 :(得分:1)
我的一般经验法则:在使用继承之前,请考虑合成是否更有意义。
原因:子类化通常意味着更多的复杂性和连通性,即更难以改变,维护和扩展而不会出错。
更完整,更具体的answer from Tim Boudreau太阳:
我认为使用继承的常见问题是:
- 无辜的行为会产生意想不到的结果 - 这个经典的例子是从超类中调用可覆盖的方法 构造函数,在子类实例字段之前 初始化。在一个完美的世界里,没有人会这样做。这是 不是一个完美的世界。
- 它为子类提供了不正确的诱惑,以便对方法调用的顺序做出假设等等 - 这种假设往往不会 如果超类可能会随着时间的推移而变得稳定。另请参阅my toaster and coffee pot analogy。
- 类变得越来越重 - 你不一定知道你的超类在它的构造函数中做了什么工作,或者它的内存是多少 使用。因此,构建一些无辜的轻量级对象可以 比你想象的要贵得多,如果这种情况可能会随着时间而改变 超类演变
- 它鼓励子类爆炸。类加载成本时间,更多类成本内存。这可能是一个非问题,直到你 处理NetBeans规模的应用程序,但在那里,我们有真实的 例如,由于第一个显示器,菜单很慢 一个菜单触发了大量的类加载。我们通过迁移来解决这个问题 更多的声明性语法和其他技术,但这需要花费时间 也可以修复。
- 这使得以后更改内容变得更加困难 - 如果你公开了一个类,那么交换超类会打破子类 - 这是一个选择,一旦你公开了代码,你就结婚了 至。所以,如果你没有改变你的真实功能 如果你超级,那么你以后可以更自由地改变事物 使用,而不是扩展你需要的东西。举个例子, 子类化JPanel - 这通常是错误的;如果子类是 在某个地方公开,你永远不会有机会重新审视这个决定。如果 它作为JComponent getThePanel()访问,你仍然可以这样做(提示: 公开API中的组件模型。
- 对象层次结构不能扩展(或者使它们扩展比以后规划要困难得多) - 这是经典的“太多层次” 问题。我将在下面讨论,以及AskTheOracle模式如何 解决它(虽然它可能冒犯OOP纯粹主义者)。
...
如果你允许继承,我可以做什么 拿一粒盐是:
- 除了常量
之外,不要公开任何字段- 方法应为抽象或最终
- 从超类构造函数中调用no方法
...
所有这些对小型项目的应用较少,而不是大型项目 私人课程而非公共课程