Reputation: 8360
I have a class PageRankMonteCarlo
that extends PageRankSparse
. PageRankMonteCarlo
has a constructor which is called in main()
. Inside of the constructor, PageRankSparse.readDocs()
is called, to set up some variables of the PageRankMonteCarlo
object.
When I run PageRankMonteCarlo
, the constructor of PageRankSparse
is executed, even though I don't want it to. This leads to readDocs
being called twice, since readDocs
is also called in PageRankSparse()
. Here's the code:
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] );
}
}
}
The output:
reading...
reading...
NUMBER_OF_DOCS: 0
As you can see, readDocs
has been executed twice. This leads to unintended behaviour.
How can I make sure readDocs
is only executed one time? I've tried this (removing readDocs()
call from subclass constructor):
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);
}
}
But there are two problems:
String filename
to subclass constructor when it doesn't even use it.PageRankMonteCarlo(String filename)
to be executed. Instead, PageRankMonteCarlo()
is executed.How can I get the behaviour I want?
Upvotes: 0
Views: 45
Reputation: 3453
Just pass the filename to the superclass constructor. If it's something the superclass also needs to do, it should be handled in the superclass.
public PageRankMonteCarlo(String filename) {
super(filename);
System.out.printf("NUMBER_OF_DOCS: %d\n", NUMBER_OF_DOCS);
}
If you need to avoid doing something that the superclass constructor does (like the iterate
call), you could make it conditional with another parameter:
public PageRankSparse( String filename, boolean doIterate ) {
int noOfDocs = readDocs( filename );
NUMBER_OF_DOCS = noOfDocs;
if (doIterate) {
iterate( noOfDocs, 1000 );
}
}
and have the subclass call super(filename, false);
.
Also, I would recommend removing that "for testing" no-arg constructor, which is what the subclass constructor is calling now (all constructors will automatically call super()
unless a super call is specified). You can test the class by calling the normal constructor with "links5.txt"
.
Upvotes: 1