超级类的构造函数是在我不想要它的情况下输入的

时间:2018-03-01 18:44:23

标签: java

我有一个扩展PageRankMonteCarlo的课程PageRankSparsePageRankMonteCarlo有一个在main()中调用的构造函数。在构造函数内部,调用PageRankSparse.readDocs()来设置PageRankMonteCarlo对象的一些变量。

当我运行PageRankMonteCarlo时,PageRankSparse的构造函数被执行,即使我不想要它。这会导致readDocs被调用两次,因为在readDocs中也会调用PageRankSparse()。这是代码:

PageRankMonteCarlo.java:

package pagerank;

public class PageRankMonteCarlo extends PageRankSparse {

    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Please provide a filename");
        }
        new PageRankMonteCarlo(args[0]);
    }

    public PageRankMonteCarlo(String filename) {
        NUMBER_OF_DOCS = readDocs(filename);
        System.out.printf("NUMBER_OF_DOCS: %d\n", NUMBER_OF_DOCS);

    }
}

PageRankSparse.java:

public class PageRankSparse {


    public PageRankSparse( String filename ) {
    int noOfDocs = readDocs( filename );
    NUMBER_OF_DOCS = noOfDocs;
    iterate( noOfDocs, 1000 );
    }

    // For testing
    public PageRankSparse() {
            int noOfDocs = readDocs("links5.txt");
            NUMBER_OF_DOCS = noOfDocs;
    }


    /* --------------------------------------------- */


    /**
     *   Reads the documents and fills the data structures. 
     *
     *   @return the number of documents read.
     */
    int readDocs( String filename ) {
        int fileIndex = 0;
        System.out.println("reading...");
    }

    public static void main( String[] args ) {
    if ( args.length != 1 ) {
        System.err.println( "Please give the name of the link file" );
    }
    else {
        new PageRankSparse( args[0] );
    }
    }
}

输出:

reading...
reading...
NUMBER_OF_DOCS: 0

如您所见,readDocs已执行两次。这会导致意外行为。

如何确保readDocs仅执行一次?我试过这个(从子类构造函数中删除readDocs()调用):

public class PageRankMonteCarlo extends PageRankSparse {


    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Please provide a filename");
        }
        new PageRankMonteCarlo(args[0]);
    }

    public PageRankMonteCarlo(String filename) {
        System.out.printf("NUMBER_OF_DOCS: %d\n", NUMBER_OF_DOCS);
    }
}

但有两个问题:

  1. String filename传递给子类构造函数甚至不使用它时感觉很奇怪。
  2. 调用错误的超类构造函数。我希望PageRankMonteCarlo(String filename)被执行。而是执行PageRankMonteCarlo()
  3. 如何获得我想要的行为?

1 个答案:

答案 0 :(得分:1)

只需将文件名传递给超类构造函数即可。如果它是超类也需要做的事情,它应该在超类中处理。

public PageRankMonteCarlo(String filename) {
    super(filename);
    System.out.printf("NUMBER_OF_DOCS: %d\n", NUMBER_OF_DOCS);
}

如果您需要避免执行超类构造函数所做的事情(例如iterate调用),您可以使用其他参数使其成为条件:

public PageRankSparse( String filename, boolean doIterate ) {
    int noOfDocs = readDocs( filename );
    NUMBER_OF_DOCS = noOfDocs;
    if (doIterate) {
        iterate( noOfDocs, 1000 );
    }
}

并让子类调用super(filename, false);

另外,我建议删除“for testing”no-arg构造函数,这是子类构造函数现在调用的内容(除非指定了超级调用,否则所有构造函数都将自动调用super())。您可以通过使用"links5.txt"调用普通构造函数来测试该类。