问题描述
我有一个Wicket页面类,根据抽象方法的结果设置页面标题。
I have a Wicket page class that sets the page title depending on the result of an abstract method.
public abstract class BasicPage extends WebPage {
public BasicPage() {
add(new Label("title", getTitle()));
}
protected abstract String getTitle();
}
NetBeans警告我构造函数中的可覆盖方法调用,但是应该是什么错误呢?唯一的选择我可以想象是将其他抽象方法的结果传递给子类的超级构造函数。
NetBeans warns me with the message "Overridable method call in constructor", but what should be wrong with it? The only alternative I can imagine is to pass the results of otherwise abstract methods to the super constructor in subclasses. But that could be hard to read with many parameters.
推荐答案
从构造函数调用可覆盖方法
简单地说,这是错误的,因为它不必要地打开了多个错误的可能性。当调用 @Override
时,对象的状态可能不一致和/或不完整。
On invoking overridable method from constructors
Simply put, this is wrong because it unnecessarily opens up possibilities to MANY bugs. When the @Override
is invoked, the state of the object may be inconsistent and/or incomplete.
from Effective Java 2nd Edition,Item 17:Design and document for inheritance,or else prohibit it
A quote from Effective Java 2nd Edition, Item 17: Design and document for inheritance, or else prohibit it:
:
public class ConstructorCallsOverride {
public static void main(String[] args) {
abstract class Base {
Base() { overrideMe(); }
abstract void overrideMe();
}
class Child extends Base {
final int x;
Child(int x) { this.x = x; }
@Override void overrideMe() {
System.out.println(x);
}
}
new Child(42); // prints "0"
}
}
c $ c> Base 构造函数调用 overrideMe
,子
尚未完成初始化 final int x
,并且该方法获取错误的值。
Here, when Base
constructor calls overrideMe
, Child
has not finished initializing the final int x
, and the method gets the wrong value. This will almost certainly lead to bugs and errors.
- 从父类构造函数调用重写方法
- FindBugs - Uninitialized read of field method called from constructor of superclass
具有许多参数的构造函数可能导致可读性差,并且存在更好的替代方案。
Constructors with many parameters can lead to poor readability, and better alternatives exist.
以下是 Effective Java第2版的引用:第2项:面对许多构造函数参数时考虑一个构建器模式:
Here's a quote from Effective Java 2nd Edition, Item 2: Consider a builder pattern when faced with many constructor parameters:
伸缩构造函数模式本质上是这样的:
The telescoping constructor pattern is essentially something like this:
public class Telescope {
final String name;
final int levels;
final boolean isAdjustable;
public Telescope(String name) {
this(name, 5);
}
public Telescope(String name, int levels) {
this(name, levels, false);
}
public Telescope(String name, int levels, boolean isAdjustable) {
this.name = name;
this.levels = levels;
this.isAdjustable = isAdjustable;
}
}
现在您可以执行以下任何操作: / p>
And now you can do any of the following:
new Telescope("X/1999");
new Telescope("X/1999", 13);
new Telescope("X/1999", 13, true);
但是,目前不能只设置名称
和 isAdjustable
,并在默认情况下保留级别
。你可以提供更多的构造函数重载,但是显然数量会随着参数数量的增长而爆炸,你甚至可能有多个 boolean
和 int
参数,这将真的使一些乱七八糟的东西。
You can't, however, currently set only the name
and isAdjustable
, and leaving levels
at default. You can provide more constructor overloads, but obviously the number would explode as the number of parameters grow, and you may even have multiple boolean
and int
arguments, which would really make a mess out of things.
正如你可以看到,这不是一个令人愉快的模式写,甚至更少使用愉快(这里的真是什么意思?13是什么?)。
As you can see, this isn't a pleasant pattern to write, and even less pleasant to use (What does "true" mean here? What's 13?).
Bloch建议使用构建器模式,
Bloch recommends using a builder pattern, which would allow you to write something like this instead:
Telescope telly = new Telescope.Builder("X/1999").setAdjustable(true).build();
请注意,现在参数已命名,您可以按任何顺序设置它们,可以跳过要保留的默认值。这确实比伸缩式构造函数好得多,特别是当有大量的参数属于许多相同类型时。
Note that now the parameters are named, and you can set them in any order you want, and you can skip the ones that you want to keep at default values. This is certainly much better than telescoping constructors, especially when there's a huge number of parameters that belong to many of the same types.
- 有效的Java第2版,第2项:当面对许多构造函数参数时,考虑一个构建器模式()
- Wikipedia/Builder pattern
- Effective Java 2nd Edition, Item 2: Consider a builder pattern when faced with many constructor parameters (excerpt online)
- When would you use the Builder Pattern?
- Is this a well known design pattern? What is its name?
这篇关于在构造函数中的可重写方法调用有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!