有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从父类中调用父方法

以下是我的代码摘录

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<Entry>dict数据库之外,还有其他简洁的解决方案吗


共 (3) 个答案

  1. # 1 楼答案

    你可以这样解决:

    • 创建CwDB.add的私有(或最终)版本,让我们称之为privateAdd

    • CwDB中的旧add方法调用此方法

    • 每当您想确保使用CwDB版本的add时,只需调用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正确指出的那样:永远不要从构造函数中(直接或间接)调用虚方法。原因很简单:子类将在其超类(及其本身)正确初始化之前运行代码。(不过,它是否适用于这个特定的例子是有道理的。)

  2. # 2 楼答案

    您遇到了不应该从构造函数调用虚拟方法的原因之一。有关这方面的更多详细信息,请参见Effective Java 2nd Edition,第17项:继承的设计和文档,或者禁止它

    解决问题的最简单方法是将基类方法拆分为一个非虚拟(final和/或private)方法和另一个虚拟方法,后者在基类实现中调用前者

    @aioobe更快地提供了一个例子:-)

  3. # 3 楼答案

    我将把add方法移动到CwDB中的addInternal,并创建一个新的add调用addInternal。然后在createDB方法中,调用addInternal以获得正确的方法。 例如

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