【问题标题】:In Java, can a variable or parameter set the parent of a subclass?在Java中,变量或参数可以设置子类的父类吗?
【发布时间】:2021-02-27 01:17:01
【问题描述】:

上下文

我正在使用带有 JPanel 等的 Swing 以及其他 JComponent 创建一个 RPG 字符生成器程序,这些组件根据依赖项列表以特定顺序返回它们的数据(见下文)。我希望组件包含一些额外的数据和功能,所以我可能想要扩展,比如

NewField 扩展了 JTextField

NewButton 扩展了 JButton

NewLabel 扩展了 JLabel 等等。

问题

我可以手动输入这些,当然!但是它们都会有共同的变量,比如“依赖列表”或“InitialOrder”等等。 我正在寻找一种能够提供该模板数据(包括函数和局部变量)的关系。我试过了……

  1. 接口,但不会创建非静态变量
  2. 扩展 JComponents 的超类,但不包括 JTextField 和 JButton 方法的细节。我必须在那个新课程中重新声明所有内容,而且我宁愿避免这样做。
  3. 创建 JComponent 对象并在需要时返回该对象的通用类,但这是一个纯粹的 JTextField 组件。 “getDependencies”不起作用,我仍然需要一个完整的列表。即使在整个情况下,设置限制也无济于事。

注意:依赖项只是必须首先读取的字段列表,因为用户可以在文本文件中定义条件来更改某些内容。例如,如果用户希望房屋数量在 50 到 100 之间,并且每所房屋大约 3 到 5 人,则 NUMBEROFHOUSES 字段必须在 NUMBEROFRESIDENTS 字段生成其值之前生成一个值,因为它必须这样做次数等于 NUMBEROFHOUSES 生成的值。 NUMBEROFRESIDENCES 的依赖关系列表将包含 NUMBEROFHOUSES,这意味着当读取所有字段的列表时,“GENERATE NUMBEROFHOUSES”字符串将位于“GENERATE NUMBEROFRESIDENCES”字符串之前。 依赖项只是一个“确保首先读取这些字段”列表

问题

像创建泛型对象的泛型一样,我可以定义一个扩展基于另一个变量或参数的类吗?

例如:类 NewComp 扩展 T

类 NewButton 扩展 NewComp

示例


当前方法

class NewButton extends JButton{
    private ArrayList<String> dependencies;
    NewButton(){super();}
    public ArrayList<String> getDependencies{return dependencies;}
    public void setDependencies(ArrayList<String> newDeps){dependencies = newDeps;}
}

class NewTextField extends JTextField{
    private ArrayList<String> dependencies;
    NewTextField (){super();}
    public ArrayList<String> getDependencies{return dependencies;}
    public void setDependencies(ArrayList<String> newDeps){dependencies = newDeps;}
    public void aSpecificNewTextFieldMethod(){...}
}

class NewLabel extends JLabel{
    private ArrayList<String> dependencies;
    NewLabel (){super();}
    public ArrayList<String> getDependencies{return dependencies;}
    public void setDependencies(ArrayList<String> newDeps){dependencies = newDeps;}
    public void firstNewLabelMethod(){...}
    public void secondNewLabelMethod(){...}
}

class CompManager{
    private JPanel p;
    CompManager(JPanel p){
    this.p = p;

    p.add(new NewButton(), new NewTextField().setText("Fake"), new NewLabel());

    Component[] c = p.getComponents();

    for(Component comp: c){

        if(comp.getClass().equals(NewField)) {//do something}

    }
}

有问题的方法


class NewComp extends <T>{
    private ArrayList<String> dependencies;
    NewComp(){Super();}
    public ArrayList<String> getDependencies{return dependencies;}
    public void setDependencies(ArrayList<String> newDeps){dependencies = newDeps;}
}

class NewButton extends NewComp<JButton>{
    NewButton(){super();}
}

class NewTextField extends NewComp<JTextField>{
    NewTextField (){super();}
    public void aSpecificNewTextFieldMethod(){...}
}

class NewLabel extends NewComp<JLabel>{
    NewLabel (){super();}
    public void firstNewLabelMethod(){...}
    public void secondNewLabelMethod(){...}
}

class CompManager{
    private JPanel p;
    CompManager(JPanel p){
    this.p = p;

    p.add(new NewButton(), new NewTextField().setText("Fake"), new NewLabel());

    Component[] c = p.getComponents();

    for(Component comp: c){

        if(comp.getClass().equals(NewField)) {//do something}

    }
}

即使答案是否定的,我也很想听听一些替代解决方案! 如果我没有把问题说清楚,请说清楚!

【问题讨论】:

  • 你过度思考你的问题,最重要的是过度使用继承,如果你继续走这条路,我认为你正在走向编码噩梦。更多地关注组合的使用、简单性和限制复杂性(圈复杂性)
  • 例如,关于我使用和创建的组件(我已经使用过很多),我大约有 5% 的时间继承了 GUI 组件(主要是需要重写其paintComponent 来进行绘图的 JPanel ) 和其他 95% 的时间,使用直接的 GUI 组件,这些组件根据需要设置了属性,但不是继承的。如果需要许多具有相似属性的,我将通过工厂方法来完成。
  • 还有建议,摆脱不必要的喋喋不休的问题,而是专注于让您的问题易于理解。一个小的可编译可运行代码示例将大大有助于实现这一目标。一定要浏览help center 链接、minimal reproducible example 链接和How to Ask 链接,看看如何改进这个和你未来的问题。
  • 感谢您的反馈!虽然我认为设置和上下文可以解释我的思维过程,但清晰不会伤害!基本上我想重写 JComponent 类来添加更多的方法/变量。我会查找工厂方法,我以前见过一次弹出...再次感谢,注意安全!
  • 另外,查找 M-V-C 设计模式(代表模型-视图-控制器),然后研究它。然后,您可能希望更多地关注模型而不是视图(您目前正在这样做)

标签: java swing oop polymorphism relationship


【解决方案1】:

我可以定义一个扩展基于另一个变量或参数的类吗?

是的,经过进一步考虑,事实上,您可以。像这样的东西被称为Abstract Factory Design Pattern(请查看链接以获得关于此的体面教程)。这允许您创建具有特定特征的类的对象,这些特征可以在运行时确定,这是我认为您正在尝试做的事情。因为工厂是“抽象的”(通常从一个接口开始),您可以根据需要和程序的发展灵活地创建它的多个具体版本,然后可以使用创建的每个具体工厂来创建多个不同的组件(或逻辑实体)。它非常强大且非常灵活。

话虽如此,我仍然支持我为您的原始帖子所做的大部分内容,包括:

  • 您可能过度使用继承,而不是专注于通过组合更易于使用的扩展
  • 也许需要更多地关注程序的 模型非 GUI 逻辑基础与构成其他主要部分的具体 GUI 组件分开程序的视图
  • 至于 Swing,我仍然建议避免继承您创建和使用的大部分 Swing 组件,而是使用“开箱即用”的组件,但需要设置属性,如果您需要创建多个组件,请使用工厂方法类似的组件,并且仅在需要覆盖具体组件的行为时使用继承,例如在 JPanel 中进行绘图。
  • 查找代表模型-视图-控制器的 M-V-C 设计模式,然后首先关注代码的模型部分,因为您描述的大部分内容都属于那里,而不是适当的 GUI 组件(再次,视图)。

【讨论】:

  • 感谢您的回答,绝对是一本好书!我将编辑我的问题以给出一个具体的场景;我认为抽象工厂设计模式太灵活了,因为我只想为每个添加大约 3 个方法和变量。此外,他们的阅读顺序并不是由用户真正设置的,或者至少不是必需的:有一个模板文件可以根据需要进行更改,但大多数用户会按原样使用它。虽然我认为我说得不够清楚,所以那是我的错。我会尽量说清楚!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-22
  • 2018-12-31
  • 1970-01-01
  • 2017-10-28
  • 2022-08-16
  • 2021-11-30
  • 1970-01-01
相关资源
最近更新 更多