Java 中的链接构造函数

Chaining Constructors in Java

想不出更好的标题。

一个classic学习例子:classHuman,其中属性为姓名、年龄、母亲和父亲。 parents 也是 Human

public class Human {
    String name;
    int age;
    Human mother;
}

我想创建 3 个构造函数:

  1. Human();
  2. Human(String name, int age);
  3. Human(String name, int age, Human mother).

猜测我确实理解链接是如何工作的,这就是我所做的:

Human() {
    this("Jack", 22);
}

Human(int age, String name) {
    this(age, name, new Human()); // new Human() will cause SOF Error.
}

Human(int age, String name, Human mother) {
    this.age = age;
    this.name = name;
    this.mother = mother;
}

如上所述,我收到WhosebugError,我再次猜测我知道为什么会这样。 尽管公平地说,我想我会得到像人类杰克那样的东西,他的母亲也是人类杰克

不过,我不知道应该怎么做。我的猜测是,我应该使用所有参数调用构造函数,而不是 new Human(),但我不确定它是否正确以及唯一可用的选项。

在此感谢任何指导。

是的,你说得对。不过可以肯定的是:

  • new Human() 呼叫 this("Jack", 22)
  • this("Jack", 22) 呼叫 this(age, name, new Human())
  • 里面的new Human()再调用this("Jack", 22)
  • 再次调用 this(age, name, new Human())
  • 直到你运行出栈

正确的做法是确保您不会回到起点。因此,如果您在任何构造函数中使用 new Human(String)new Human(String, int),则必须确保该构造函数(new Human(String)new Human(String, int))不会同时使用 new Human(String)new Human(String, int),因为你最终会无休止地递归。您需要在某处使用 new Human(String, int, Human) 。例如:

Human(int age, String name) {
    this(age, name, null);
}

当然,这意味着新实例将有 null for mother

Human() {
    this.name = "Jack";
    this.age = 22;
}

Human(int age, String name) {
    this.age = age;
    this.name = name;
    this.mother = null;
}

Human(int age, String name, Human mother) {
    this.age = age;
    this.name = name;
    this.mother = mother;
}

这不会创建任何分层或嵌套的构造函数

如果我没看错你的问题,有两个sub-questions:

  1. Java语言(使用构造函数)中是否有不同的方法?
  2. 在Object-Oriented设计中有更好的方法吗?

回复第一个问题,一个构造函数就是一个方法,你的实现结果是两个递归的方法。您必须打破递归或引入退出条件。还有 另一种选择 - 在第一个构造函数中调用 this(age, name, null)

关于第二个问题,一个流行的解决方案是 simple factory 模式,其中你只有一个 private 构造函数和所有参数,然后是几个 public 工厂方法做任何你想做的事。

您的构造函数 Human(int, String) 执行没有任何条件的递归,最终创建 WhosebugError.

构造函数重载是一种非常常用的方法,它提供了创建对象的便捷方法。只要成员不是 final 并且以后可能会被操纵,您最好不要传递任何值(又名 null),而不是即时创建更多对象。

实际上没有人没有 母亲 但它可能是未知的所以现在通过 null 是更好的方法。

如果您需要 mother 不可变,则不得提供任何构造函数而没有为 mother 提供引用以使其清晰可见。即使这样也行不通,因为你无法为人类的起源提供这样一个无尽的树结构。通常这样的结构有一个 "root" 对象,它没有父对象(或本例中的 mother)。

我建议不要使用构造函数链接。例如,我更愿意使用变量链接并使用构建器设计模式以及节点类型的数据结构。

Class Human{
int age;
Sting name;
Human mother;

public  Human setAge(int age){
this.age = age;    
return this;
}

public Human setName(String name){
this.name = name;
return this;
}

public Human setHuman(Human mother){
this.mother= mother;
return this;
}

}

执行此操作后,您可以将第一个母亲实例创建为人类,然后将其设置为儿童的人类。让我知道更具体的答案。