从父类内部调用父方法

发布于 2024-09-28 10:02:45 字数 1461 浏览 5 评论 0原文

的摘录

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无名指的心愿 2024-10-05 10:02:45

您经历了不应从构造函数调用虚拟方法的原因之一。有关此内容的更多详细信息,请参阅 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/or private) one, and another, virtual, method, which calls the former in the base class implementation.

@aioobe was faster to provide an example to this :-)

江南烟雨〆相思醉 2024-10-05 10:02:45

您可以这样解决它:

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

  • CwDB 中旧的 add 方法改为调用此方法。

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

You could solve it like this:

  • Create a private (or final) version of the CwDB.add, lets call it privateAdd.

  • Let the old add method in CwDB call this method instead.

  • Whenever you want to be sure that the CwDB-version of add is used, you simply call privateAdd instead.

Sample code

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

    // ...
}

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

夜清冷一曲。 2024-10-05 10:02:45

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

I would move the add method to addInternal in CwDB, and make a new add which calls addInternal. Then in the createDB method, call addInternal to get the correct method.
Eg.

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);
      ..
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文