我主要使用动态语言 - 我刚刚开始使用Java,我正在努力使用静态模式。
根据我的理解,子类的构造函数中的第一个调用必须是它的父类。这很好,但是我需要在子节点的构造函数中引用子节点中设置实例变量...当然,这会创建一个catch-22。 (需要在调用parent之前在子节点中设置变量,但需要在child中设置变量之前调用parent)。
我确信我正在破坏某种静态语言模式或法律......我只是不确定是哪一种,或者如何重新设计它。任何帮助赞赏。简化下面的例子:
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;
}
}
答案 0 :(得分:6)
你的构造函数中有副作用,这是不赞成的。为获得最佳效果,请将副作用放在其他方法中。你已经有了这个,所以只需在javadoc中指定在构造之后应该调用greeting()
(或者,它可以由子类构造函数调用,但是子子类会有同样的问题)。
答案 1 :(得分: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 */
}
答案 2 :(得分: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);
}