我有一个扩展PageRankMonteCarlo
的课程PageRankSparse
。 PageRankMonteCarlo
有一个在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);
}
}
但有两个问题:
String filename
传递给子类构造函数甚至不使用它时感觉很奇怪。PageRankMonteCarlo(String filename)
被执行。而是执行PageRankMonteCarlo()
。如何获得我想要的行为?
答案 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"
调用普通构造函数来测试该类。