Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在super()之前调用子属性?_Java - Fatal编程技术网

Java 在super()之前调用子属性?

Java 在super()之前调用子属性?,java,Java,我主要使用动态语言——我刚刚开始使用Java,正在与静态模式作斗争 据我所知,子类构造函数中的第一个调用必须是对其父类的调用。这很好,但我需要在子对象中设置实例变量,这些变量在父对象的构造函数中引用……当然,这会创建一个catch-22。(在调用父级之前需要在子级中设置变量,但在子级中设置变量之前需要调用父级) 我肯定我打破了某种静态语言模式或规律……我只是不确定是哪一种,或者如何重新设计它。谢谢你的帮助。下面是一个简单的例子: Class Race { public Race(Venue

我主要使用动态语言——我刚刚开始使用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;
  }
}

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

我假设每个种族都有一个距离,那么为什么不将此字段作为超类型的一部分呢。然后可以通过提供给构造函数的参数设置此字段

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;
  }
}
将距离作为参数提供给超级构造函数:

Class Sprint extends Race {
  private int event_distance;

  public Child(Venue event_venue, int distance) {
    super(event_venue, distance);
  }
  /* omitted rest of class */
}

是的,那不行

您需要重构代码,使其能够以正确的顺序执行构造函数。通常,如果构造函数没有副作用,并且不调用可以在子类中重写的方法(两者都是不推荐的模式),那么这就不是问题


这很好,但我需要在子对象中设置实例变量,这些变量在父对象的构造函数中引用。您的父对象不应该知道子对象。您的意思是希望在创建新的Sprint对象时调用
Sprint 35; getName()
,我理解正确吗?@TheNewIdiot,这是否意味着老年退休金计划的问题无法解决?如果不是“了解未来”儿童,那么抽象的方法是什么?如果你是对的,那是一个糟糕的设计。父类应该是抽象的。
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);
}