【问题标题】:Confused by the use of Parent to Child in a constructor在构造函数中使用 Parent to Child 感到困惑
【发布时间】:2013-05-15 02:50:52
【问题描述】:

我希望我能就这个问题得到一些澄清。所以类层次结构如下所示: AbstractClass、ConcreteClass1 和 ConcreteClass2。 ConcreteClass1 扩展 AbstractClass 和 ConcreteClass2 扩展 ConcreteClass1:

ConcreteClass1 中的构造函数如下所示:

private final AbstractClass parent;

public ConcreteClass1( int id, AbstractClass aParent )
{
  super( id );

  parent = aParent;
}

我想知道这在什么情况下可能有用。除非为 aParent 参数传递 null,否则我看不到如何实例化 ConcreteClass1。 ConcreteClass2 中使用了类似的构造函数(即它也有一个 AbstractClass 类型的参数)。

这可能是一个合理的设计吗?

【问题讨论】:

  • 我看不出有什么困扰你。例如,这正是 SWT 小部件类的工作方式。
  • 这完全取决于您的域。在类之间建立父子关系可能很有用,但在技术上不需要它来使继承工作。
  • 对我来说看起来像一个树结构。 ConcreteClass1 对象引用了另一个 AbstractClass 对象。
  • 为什么你认为只有aParent参数为null才能实例化ConcreteClass1?这可能有助于我们了解您的问题
  • @MarkoTopolnik 感谢您的快速回复,我没有使用过 SWT 小部件,所以我不熟悉它,我会检查一下。

标签: java inheritance constructor abstraction


【解决方案1】:

是的,第一次要获取实例时,必须传递null,但以后可以传递以前创建的实例。

这很常见,在许多框架和库中都有使用,例如 Qt 的 QObject 就是这样,目的是创建运行时实例的分层树。很明显,这棵树的根不能也不应该有父级。

编辑: 举个实际例子,左边的树是你的类继承树,右边的树是运行时对象树的例子。请注意,实例可以是AbstractClass 的任何子类。

(CC1 表示ConcreteClass,CC2 表示ConcreteClass2

         AbstractClass                           X (NULL)
               |                                 |
               |                                 |
        ConcreteClass1                        root:CC1
               |                             /        \
               |                            /          \
        ConcreteClass2                 ins2:CC2      ins3:CC1
                                           |          /    \
                                           |         /      \
                                       ins4:CC1   ins5:CC2  ins6:CC2
                                       ...        ...       ...

【讨论】:

  • 这正是我的想法,但不确定这是否是个好主意。正如我还提到的,ConcreteClass2 使用了类似的构造函数,这意味着任何 AbstractClass 类型的对象都可以在实例化时作为它的父对象传递,这不会导致问题吗?
  • 不,因为这并不意味着树的节点必须是顶级类的直接实例,而只是任何子类的实例,这使得所有它们间接地是顶级类的实例。在上面提到的示例中,每个节点都可以是不同类的实例,但是所有这些类都继承QObject,因此所有实例都可以称为QObject 的实例。这个例子中树的目的是链接到所有创建的实例,并在最后自动释放它们;某种垃圾收集。
  • 我用提到的树的一个实际例子更新了我的答案。
  • 再次感谢穆萨。请注意,我提到 CC2 扩展了 CC1,因此如果 CC1 中的构造函数采用 AC 类型的任何内容,这意味着 CC2 也可以作为 CC1 父级传递。因此,当创建树中的不同对象时,可能会使用错误的类型。那么为什么要创建一个 CC1 对象,CC2 作为其父对象呢?
  • 如果“错误类型”是指parent 中有一些约束,那么您应该强制执行该约束,例如通过将 CC2 ctor 中的父类型从 AS 更改为 CC1。但总的来说,这没有问题。它之所以受欢迎,取决于具体情况。对于 Qt 示例,每个节点的生命周期都是父节点的子集,这意味着如果要销毁父节点,那么它的所有子节点也应该被销毁。所以他们不关心实例是什么类型,只要是 QObject 的实例就足够了。
【解决方案2】:

它在任何层次结构或继承类型布局中都特别有用。

例如,假设鼠标单击 GUI 元素。假设你的类有一个方法

handleClick(int x, int y);

第一次点击可以由底层组件处理,并且拥有父级允许结构将点击传递给父级。这类似于向上链接方法/事件。

或者,这也可以由一些外部控制器来完成,该控制器管理调用 click 方法的哪些元素,但它可能比仅使用父模型更复杂,或者只是不太干净(尽管并非总是如此)。

在这种类型的模型中,只有当它是顶级元素时,“父级”才会为空,其余的只会让父级离顶部更近一步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多