从父类内部调用父方法
的摘录
package dictionary;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.regex.*;
public class IntelliCwDB extends CwDB {
public IntelliCwDB(String filename) {
super(filename);
}
@Override
public void add(String word, String clue) {
System.out.println("inelli");
}
}
这是我的代码和 CwDB
package dictionary;
import java.util.LinkedList;
import java.io.*;
import java.util.Scanner;
public class CwDB {
protected LinkedList<Entry> dict;
public CwDB(String filename) {
dict = new LinkedList<Entry>();
createDB(filename);
}
public void add(String word, String clue) {
System.out.println("cwdb");
dict.add(new Entry(word, clue));
}
protected void createDB(String filename) {
try {
BufferedReader f = new BufferedReader(new FileReader(filename));
while (f.ready()) {
this.add(f.readLine(), f.readLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
...在 main()
部分中,我创建了一个新的 IntelliCwDB
对象,该对象触发 createDB()< /代码>。
问题是我希望 CwDB.createDB()
使用它自己的 CwDB.add()
方法,而不是来自 IntelliCwDB
的方法。除了单独创建 CwDB,然后将其传递到 IntelliCwDB 的构造函数中以重写 LinkedList
Here's an excerpt from my code
package dictionary;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.regex.*;
public class IntelliCwDB extends CwDB {
public IntelliCwDB(String filename) {
super(filename);
}
@Override
public void add(String word, String clue) {
System.out.println("inelli");
}
}
And CwDB...
package dictionary;
import java.util.LinkedList;
import java.io.*;
import java.util.Scanner;
public class CwDB {
protected LinkedList<Entry> dict;
public CwDB(String filename) {
dict = new LinkedList<Entry>();
createDB(filename);
}
public void add(String word, String clue) {
System.out.println("cwdb");
dict.add(new Entry(word, clue));
}
protected void createDB(String filename) {
try {
BufferedReader f = new BufferedReader(new FileReader(filename));
while (f.ready()) {
this.add(f.readLine(), f.readLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the main()
part I create a new IntelliCwDB
object, which fires the execution of createDB()
.
The problem is that I want CwDB.createDB()
to use it's own CwDB.add()
method, not the one from IntelliCwDB
. Is there any other neat solution than creating CwDB
separately, then passing it into the constructor of IntelliCwDB
just to rewrite the LinkedList<Entry>
dict database?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您经历了不应从构造函数调用虚拟方法的原因之一。有关此内容的更多详细信息,请参阅 Effective Java 第 2 版,第 17 项:设计和记录继承,否则禁止继承。。
解决您的问题的最简单的解决方案是将基类方法拆分为一个非虚拟(
final
和/或private
)方法,以及另一个虚拟方法,该方法调用前者在基类实现中。@aioobe 更快地提供了一个例子:-)
You experienced one of the reasons why one should not call virtual methods from a constructor. For more details on this, see Effective Java 2nd Edition, Item 17: Design and document for inheritance or else prohibit it.
The simplest solution to your problem would be to split the base class method into a nonvirtual (
final
and/orprivate
) one, and another, virtual, method, which calls the former in the base class implementation.@aioobe was faster to provide an example to this :-)
您可以这样解决它:
创建
CwDB.add
的私有(或最终)版本,我们称之为privateAdd
。让
CwDB
中旧的add
方法改为调用此方法。每当您想确保使用
add
的CwDB
版本时,只需调用privateAdd
即可。示例代码
正如 @Péter Török 正确指出的那样:您永远不应该从构造函数中(直接或间接)调用虚拟方法。原因很简单:子类将在其超类(及其自身)正确初始化之前运行代码。 (无论它是否适用于这个特定的例子,都是有道理的。)
You could solve it like this:
Create a private (or final) version of the
CwDB.add
, lets call itprivateAdd
.Let the old
add
method inCwDB
call this method instead.Whenever you want to be sure that the
CwDB
-version ofadd
is used, you simply callprivateAdd
instead.Sample code
As @Péter Török correctly points out: You should never call a virtual method (directly or indirectly) from within a constructor. The reason is simple: The sub-class will get to run code before its super class (and itself) is initialized properly. (Whether or not it applies in this particular example stands to reason though.)
我会将
add
方法移至 CwDB 中的addInternal
,并创建一个新的add
来调用addInternal
。然后在createDB
方法中,调用addInternal
来获取正确的方法。例如。
I would move the
add
method toaddInternal
in CwDB, and make a newadd
which callsaddInternal
. Then in thecreateDB
method, calladdInternal
to get the correct method.Eg.