2

我主要使用动态语言 - 我刚刚开始使用 Java,并且正在为静态模式而苦苦挣扎。

据我了解,子类的构造函数中的第一个调用必须是其父类。没关系,但是我需要在父项的构造函数中引用子项中的实例变量……当然,这会创建一个 catch-22。(需要在调用父级之前在子级中设置变量,但在子级中设置变量之前需要调用父级)。

我确定我正在打破某种静态语言模式或法律......我只是不确定是哪一个,或者如何重新设计它。任何帮助表示赞赏。精简示例如下:

Class Race {

  public Race(Venue event_venue) {
    greeting();
  }

  public void greeting() {
    String event_greeting = String.format("The next event is: %s", getName());
    System.out.println(event_greeting);
  }

  public String getName() {
    return getClass().getSimpleName();
  }
}

Class Sprint extends Race {
  private int event_distance;

  public Sprint(Venue event_venue, int distance) {
    // super has to be the first call
    super(event_venue);
    // but I need to set event_distance to reference getName() in parent constructor
    setDistance(distance);
  }

  public String getName() {
    String sprint_name = String.format("%s meter sprint", Integer.toString(getDistance());
    return sprint_name;
  }

  public int getDistance() {
    return distance;
  }

  public void setDistance(int distance) {
    event_distance = distance;
  }
}
4

3 回答 3

6

您的构造函数中有副作用,这是不受欢迎的。为了获得最佳效果,请将副作用放在其他方法中。你已经有了这个,所以只需greeting()在构造后调用的 javadoc 中指定(或者,它可以由子类构造函数调用,但子子类也会有同样的问题)。

于 2013-07-24T08:31:53.083 回答
1

我假设每场比赛都会有一段距离,所以为什么不让这个字段成为超类型的一部分。然后可以通过提供给构造函数的参数来设置该字段。

Class Race {
  private int event_distance;
  public Race(Venue event_venue, int distance) {
    this.distance = distance;
    greeting();
  }

  public void greeting() {
    String event_greeting = String.format("The next event is: %s", getName());
    System.out.println(event_greeting);
  }

  public String getName() {
    return getClass().getSimpleName();
  }

  public int getDistance() {
    return distance;
  }

  public void setDistance(int distance) {
    event_distance = distance;
  }
}

作为参数提供distance给超级构造函数:

Class Sprint extends Race {
  private int event_distance;

  public Child(Venue event_venue, int distance) {
    super(event_venue, distance);
  }
  /* omitted rest of class */
}
于 2013-07-24T08:32:18.453 回答
0

是的,那是行不通的。

您需要重构您的代码,以便能够以正确的顺序执行构造函数。如果构造函数没有副作用并且不调用可以在子类中覆盖的方法(这两种都是不鼓励的模式),通常这不是问题。

public Race(Venue event_venue) {
  greeting();   // constructor should not call non-final method
}

// method called by a constructor should not print anything
public void greeting() {
   String event_greeting = String.format("The next event is: %s", getName());
   System.out.println(event_greeting);
}
于 2013-07-24T08:32:45.323 回答