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);
      ..
   }
}