Java 从父类内调用父方法
下面是我的代码摘录Java 从父类内调用父方法,java,methods,nested,parent,Java,Methods,Nested,Parent,下面是我的代码摘录 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 pub
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();
}
}
}
包字典;
导入java.util.LinkedList;
导入java.io.*;
导入java.util.Scanner;
公共类CwDB{
受保护的链接列表目录;
公共CwDB(字符串文件名){
dict=新链接列表();
createDB(文件名);
}
公共空白添加(字符串字、字符串线索){
System.out.println(“cwdb”);
添加(新条目(单词、线索));
}
受保护的void createDB(字符串文件名){
试一试{
BufferedReader f=新的BufferedReader(新文件读取器(文件名));
while(f.ready()){
添加(f.readLine(),f.readLine());
}
}捕获(例外e){
e、 printStackTrace();
}
}
}
在main()
第一部分中,创建一个新的IntelliCwDB
对象,该对象触发执行createDB()
问题是我希望
CwDB.createDB()
使用它自己的CwDB.add()
方法,而不是IntelliCwDB
中的方法。除了单独创建CwDB
,然后将其传递给IntelliCwDB
的构造函数以重写LinkedList
dict数据库之外,还有什么好的解决方案吗?您可以这样解决:
- 创建
CwDB.add的私有(或最终)版本,我们称之为
privateAdd
- 让
中的旧CwDB
方法调用此方法add
- 只要您想确保使用了
的add
-版本,只需调用CwDB
privateAdd
public class CwDB {
// ...
public void add(String word, String clue) {
privateAdd(word, clue);
}
private void privateAdd(String word, String clue) {
System.out.println("cwdb");
dict.add(new Entry(word, clue));
}
protected void createDB(String filename) {
// ...
// "Calling parent method from within the parent class" :-)
this.privateAdd(f.readLine(), f.readLine());
// ...
}
// ...
}
正如@péter Török正确指出的那样:您不应该从构造函数中(直接或间接)调用虚方法。原因很简单:子类将在其超类(及其本身)正确初始化之前运行代码。(不管它是否适用于这个特定的例子,这是有道理的。)我将把
add
方法移动到CwDB中的addInternal
,并创建一个新的add
调用addInternal
。然后在createDB
方法中,调用addInternal
以获得正确的方法。
例如
您遇到了不应从构造函数调用虚拟方法的原因之一。有关这方面的更多详细信息,请参见第17项:继承的设计和文档,否则禁止继承 问题的最简单解决方案是将基类方法分为非虚拟(
final
和/或private
)方法和另一个虚拟方法,后者在基类实现中调用前者
@aioobe更快地提供了一个例子:-)你需要提到的是,他应该将内部add设置为private,以确保它不会被覆盖。大多数漂亮的抽象问题都是关于谁在绘图上最快:)“绘图上最快”,在这种情况下,hahahJava是不明确的,因为据我所知,CwDB构造函数中从CwDB.add()到IntelliCwDB.add()的切换是以静默方式完成的(或者准确地说,是尚未执行的切换)。完全禁用这样的操作不是更好吗?它们在普通编程中真的有用吗?嗯。。我不知道你的意思。“切换”从未完成。所有方法从一开始都是虚拟的,即使在构造函数中也是如此。你有什么建议?方法重写?在C++中,你可以选择一种非虚拟的方法(如你在这个场景中想要的)。Java采用了另一种方法,使所有方法都是虚拟的,没有禁用它的选项。
class CwDB {
..
private void addInternal(String word, String clue) {
..
}
public void add(String word, String clue) {
addInternal(word, clue);
}
public void createDB(String filename) {
..
addInternal(w, c);
..
}
}