Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > calling own methods from constructor

Reply
Thread Tools

calling own methods from constructor

 
 
Andreas Leitgeb
Guest
Posts: n/a
 
      04-06-2011
There is well-known danger in calling own methods from the
constructor, namely that the method called may be overridden
by a subclass, which is really instanciated, but whose specific
constructor has not yet been run.

I do not intend to delve into the details of static, private
or final methods, or final'ity of the class itself (and maybe
others) avoiding these problems, but instead I'm curious, why
Java just doesn't simply forbid the dangerous calls.

Is there any *good* use of having the constructor call a method
that actually *can* be overridden in a subclass? I mean, are
there (non-anti)patterns of explicitly allowing subclasses to
hook into base-class's construction?

--- sscce Test.java begin ---
public class Test {
Test() { foo(); }
void foo() { }
}
--- sscce Test.java end ---

PS: I know that this is not the only spot where Java does let one
shoot in one's feet. But unlike other situations, this one just
seems so easy to detect from static analysis.

 
Reply With Quote
 
 
 
 
Tom Anderson
Guest
Posts: n/a
 
      04-06-2011
On Wed, 6 Apr 2011, Andreas Leitgeb wrote:

> Is there any *good* use of having the constructor call a method that
> actually *can* be overridden in a subclass? I mean, are there
> (non-anti)patterns of explicitly allowing subclasses to hook into
> base-class's construction?


public abstract class Library {
private List<Document> documents;

protected Library() {
documents = new ArrayList<Document>();
Collection<String> titles = listDocuments();
for (String title: titles) {
Document doc = loadDocument(title);
// do other preparatory stuff with the document
documents.add(doc);
}
}

protected abstract Collection<String> listDocuments();
protected abstract Document loadDocument(String title);
}

public class FilesystemLibrary extends Library {
// ...
}

public class WebDavLibrary extends Library {
// ...
}

public class JCRLibrary extends Library {
// ...
}

What are the alternatives?

The obvious one is for the subclass constructor to prepare all the objects
and pass them upward; i think that is likely to lead to a lot of
duplication of effort.

The almost as obvious one is to push the abstract methods out into a
separate interface - DocumentStore, say - and have the subclass
constructor pass up an instance of that.

You could also push the repeated logic out into some sort of factory or
helper, and have the subclasses call that, rather than relying on code in
the supeclass, but that is repetitive, and does nothing to establish
invariants in the superclass.

tom

--
Science which is distinguishable from magic is insufficiently advanced
 
Reply With Quote
 
 
 
 
Lew
Guest
Posts: n/a
 
      04-06-2011
Andreas Leitgeb wrote:
>> Is there any *good* use of having the constructor call a method that
>> actually *can* be overridden in a subclass? I mean, are there
>> (non-anti)patterns of explicitly allowing subclasses to hook into
>> base-class's construction?


import org.apache.log4j.Logger;
import static org.apache.log4j.getLogger;

public class Foo
{
private final Logger logger = getLogger( getClass() );
// ...
}


--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedi.../c/cf/Friz.jpg
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      04-07-2011
On 4/6/2011 6:06 PM, Tom Anderson wrote:
> On Wed, 6 Apr 2011, Andreas Leitgeb wrote:
>
>> Is there any *good* use of having the constructor call a method that
>> actually *can* be overridden in a subclass? I mean, are there
>> (non-anti)patterns of explicitly allowing subclasses to hook into
>> base-class's construction?

>
> public abstract class Library {
> private List<Document> documents;
>
> protected Library() {
> documents = new ArrayList<Document>();
> Collection<String> titles = listDocuments();
> for (String title: titles) {
> Document doc = loadDocument(title);
> // do other preparatory stuff with the document
> documents.add(doc);
> }
> }
>
> protected abstract Collection<String> listDocuments();
> protected abstract Document loadDocument(String title);
> }
>
> public class FilesystemLibrary extends Library {
> // ...
> }
>
> public class WebDavLibrary extends Library {
> // ...
> }
>
> public class JCRLibrary extends Library {
> // ...
> }
>
> What are the alternatives?


Safer ones, I hope. This code presupposes that the subclass
instance can do useful work before its constructor finishes -- to
put it another way, it assumes that the subclass constructor does
absolutely nothing except call the superclass constructor (and even
that much requires some leaps of faith).

How might Java ensure such an assumption? I can't imagine how
it could be done at compile time, when the suite of subclasses may
not even exist to be inspected. At run time, I guess it could be
done with two additional bits per instance: One that says "The
constructor has not yet returned" and another that says "A virtual
method has been called while the constructor is active." Each
virtual method would copy the first bit to the second, and if the
constructor found the second bit set while doing anything other
than a "return," it could throw an exception.

> The obvious one is for the subclass constructor to prepare all the
> objects and pass them upward; i think that is likely to lead to a lot of
> duplication of effort.
>
> The almost as obvious one is to push the abstract methods out into a
> separate interface - DocumentStore, say - and have the subclass
> constructor pass up an instance of that.
>
> You could also push the repeated logic out into some sort of factory or
> helper, and have the subclasses call that, rather than relying on code
> in the supeclass, but that is repetitive, and does nothing to establish
> invariants in the superclass.


It seems to me the constructor is doing too much of the heavy
lifting. A Library(Collection<Document>) constructor, with the
Documents already loaded or maybe with "load on first use" flags,
seems a more tenable approach. In particular, it allows the
subclass constructors to choose their own sets of exceptions to
throw, instead of requiring that they all extend exceptions thrown
by the superclass' abstract method declarations.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)d
 
Reply With Quote
 
Owen Jacobson
Guest
Posts: n/a
 
      04-07-2011
On 2011-04-06 16:48:41 -0400, Andreas Leitgeb said:

> There is well-known danger in calling own methods from the
> constructor, namely that the method called may be overridden
> by a subclass, which is really instanciated, but whose specific
> constructor has not yet been run.
>
> I do not intend to delve into the details of static, private
> or final methods, or final'ity of the class itself (and maybe
> others) avoiding these problems, but instead I'm curious, why
> Java just doesn't simply forbid the dangerous calls.


It's hard to prove that a constructor never calls a virtual method. Consider:

public class Foo {
public Foo() {
// internalInit is private, therefore final
this.internalInit();
}

public /* virtual */ void virtualMethod() {
System.out.println("Override me! I dare you.");
}

private void internalInit() {
// Whups! 'this' is not always fully initialized.
this.virtualMethod();
}
}

If you forbid internalInit from calling virtual methods because it is,
itself, called from a constructor, you also prevent it from calling
virtual methods when called from a normal method. If you don't prevent
that, but do prevent Foo's constructor from calling any of its own
virtual methods, then you end up with the question "why does Java make
me use a private method when I want to call a virtual method from a
constructor?" instead.

-o

 
Reply With Quote
 
Andreas Leitgeb
Guest
Posts: n/a
 
      04-07-2011
Tom Anderson <(E-Mail Removed)> wrote:
> On Wed, 6 Apr 2011, Andreas Leitgeb wrote:
>> Is there any *good* use of having the constructor call a method that
>> actually *can* be overridden in a subclass? I mean, are there
>> (non-anti)patterns of explicitly allowing subclasses to hook into
>> base-class's construction?


> public abstract class Library {
> private List<Document> documents;
> protected Library() {
> documents = new ArrayList<Document>();
> Collection<String> titles = listDocuments();
> for (String title: titles) {
> Document doc = loadDocument(title);
> // do other preparatory stuff with the document
> documents.add(doc);
> }
> }
> protected abstract Collection<String> listDocuments();
> protected abstract Document loadDocument(String title);
> }
>
> public class FilesystemLibrary extends Library {
> // ...
> }
> [...]


Sorry, in my eyes, this is one of the anti-patterns.

> What are the alternatives?


It's hard to speculate about alternatives for an artificial example.

I'd say, that they exist for any reasonable specification of the problem,
and "back it up"(*) by declaring specifications for which no (or only
mindboggingly contrived) alternatives exist as unreasonable

(*): In German, we use double-quotes also to indicate tongue-in-cheek
formulations that aren't to be taken entirely literally/serious.
I've recently learned that they are not always thusly understood,
elsewhere. Therefore this explanation. Is there any common markup
for it that would be recognized in the English-speaking world?
 
Reply With Quote
 
Andreas Leitgeb
Guest
Posts: n/a
 
      04-07-2011
Lew <(E-Mail Removed)> wrote:
> Andreas Leitgeb wrote:
>>> Is there any *good* use of having the constructor call a method that
>>> actually *can* be overridden in a subclass? I mean, are there
>>> (non-anti)patterns of explicitly allowing subclasses to hook into
>>> base-class's construction?

>
> import org.apache.log4j.Logger;
> import static org.apache.log4j.getLogger;
> public class Foo
> {
> private final Logger logger = getLogger( getClass() );
> // ...
> }


I thought, I made it clear, that calling static methods was not relevant
to my question. So, kind of thanks for pointing out that I should have
written non-static in the very line of the question, rather than consider
that clear from the other (snipped by you) paragraphs of my post...

 
Reply With Quote
 
Andreas Leitgeb
Guest
Posts: n/a
 
      04-07-2011
Owen Jacobson <(E-Mail Removed)> wrote:
> On 2011-04-06 16:48:41 -0400, Andreas Leitgeb said:
>
>> There is well-known danger in calling own methods from the
>> constructor, namely that the method called may be overridden
>> by a subclass, which is really instanciated, but whose specific
>> constructor has not yet been run.
>>
>> I do not intend to delve into the details of static, private
>> or final methods, or final'ity of the class itself (and maybe
>> others) avoiding these problems, but instead I'm curious, why
>> Java just doesn't simply forbid the dangerous calls.

>
> It's hard to prove that a constructor never calls a virtual method. Consider:
> [ example of c'tor calling a private method "internalInit", which in turn
> calls virtual "virtualMethod". ]


Good point. The compiler couldn't (at least not statically) prevent
indirect calling of overridable non-static methods.

But otoh., it refuses to compile this:
String bad = (String) new Integer(42);
while allowing this: (sure bomb at runtime)
String bad = (String) (Object) new Integer(42);

So, not being able to prevent something happening indirectly,
doesn't imply that the direct way would need to be allowed, too.

So, it boils down to the original question of whether there is also
a good use of constructors (directly or indirectly) invoking
overridable virtual methods.

What it "good"? I have no exact definition, but if one of the
Java gurus (Brian Goetz, Joshua Bloch, James Gosling,...) ever
before suggested a pattern that would involve it, then chances
are good, that I'd accept it. Also, if the JSL or one of the big
Java-based projects used it. Tom's example (Library) didn't
convince me so far.

 
Reply With Quote
 
Arved Sandstrom
Guest
Posts: n/a
 
      04-07-2011
On 11-04-07 05:36 AM, Andreas Leitgeb wrote:
[ SNIP ]

> (*): In German, we use double-quotes also to indicate tongue-in-cheek
> formulations that aren't to be taken entirely literally/serious.
> I've recently learned that they are not always thusly understood,
> elsewhere. Therefore this explanation. Is there any common markup
> for it that would be recognized in the English-speaking world?


It would be quotation marks, usually double quotes, just as in German.
Even Wikipedia (in its entry for Quotation Marks) refers to the use of
quotation not only for actual quotes, but also to denote irony or
unusual usage. Quotes are also used to indicate non-literal or
self-coined meanings, or to emphasize use of the word rather than its
meaning.

Having said that, there are varying levels of literacy in the
English-speaking world. Not everyone will be aware of the other usages
for quotation marks.

AHS
--
That's not the recollection that I recall...All this information is
certainly in the hands of the auditor and we certainly await his report
to indicate what he deems has occurred.
-- Halifax, Nova Scotia mayor Peter Kelly, who is currently deeply in
the ****
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      04-07-2011
On 06 Apr 2011 20:48:41 GMT, Andreas Leitgeb
<(E-Mail Removed)> wrote, quoted or indirectly quoted
someone who said :

>Is there any *good* use of having the constructor call a method
>that actually *can* be overridden in a subclass?


I have accidentally nailed myself by overriding a method used in a
constructor. I have yet to find a legitimate use for it. It is too
bad the compiler does not complain about it.
--
Roedy Green Canadian Mind Products
http://mindprod.com
Doing what the user expects with respect to navigation is absurdly important for user satisfaction.
~ anonymous Google Android developer

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
own initialization before calling parent's constructor avasilev C++ 23 12-09-2011 01:54 PM
A constructor calling another constructor (default constructor)? Generic Usenet Account C++ 10 11-28-2007 04:12 AM
Avoid calling non-final methods in a constructor: Applies to static methods too? Oliver Wong Java 14 06-13-2006 09:18 AM
Calling own-constructors inside another constructor EdUarDo Java 4 12-21-2005 12:23 PM
why it's not possible calling constructor from constructor? Giulio C++ 9 06-25-2003 03:56 PM



Advertisments