Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #2904 > unrolled thread
| Started by | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| First post | 2011-04-06 20:48 +0000 |
| Last post | 2011-04-08 20:02 +0200 |
| Articles | 20 on this page of 51 — 15 participants |
Back to article view | Back to comp.lang.java.programmer
calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-06 20:48 +0000
Re: calling own methods from constructor Tom Anderson <twic@urchin.earth.li> - 2011-04-06 23:06 +0100
Re: calling own methods from constructor Lew <noone@lewscanon.com> - 2011-04-06 18:24 -0400
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 08:44 +0000
Re: calling own methods from constructor Robert Klemme <shortcutter@googlemail.com> - 2011-04-07 04:14 -0700
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 12:32 +0000
Re: calling own methods from constructor Robert Klemme <shortcutter@googlemail.com> - 2011-04-07 05:55 -0700
Re: calling own methods from constructor Lew <lew@lewscanon.com> - 2011-04-07 08:10 -0700
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 20:31 +0000
Re: calling own methods from constructor Lew <lew@lewscanon.com> - 2011-04-07 14:10 -0700
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 22:15 +0000
Re: calling own methods from constructor Lew <noone@lewscanon.com> - 2011-04-07 21:22 -0400
Re: calling own methods from constructor Tom Anderson <twic@urchin.earth.li> - 2011-04-07 23:08 +0100
Re: calling own methods from constructor Lew <noone@lewscanon.com> - 2011-04-07 21:24 -0400
Re: calling own methods from constructor "Mike Schilling" <mscottschilling@hotmail.com> - 2011-04-09 22:06 -0700
Re: calling own methods from constructor Tom Anderson <twic@urchin.earth.li> - 2011-04-07 23:10 +0100
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 22:24 +0000
Re: calling own methods from constructor Lew <noone@lewscanon.com> - 2011-04-07 07:19 -0400
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 12:24 +0000
Re: calling own methods from constructor Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-04-06 20:46 -0400
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 08:36 +0000
Re: calling own methods from constructor Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-04-07 07:16 -0300
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 11:26 +0000
Re: calling own methods from constructor Paul Cager <paul.cager@googlemail.com> - 2011-04-07 03:20 -0700
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 11:36 +0000
Re: calling own methods from constructor Owen Jacobson <angrybaldguy@gmail.com> - 2011-04-06 22:23 -0400
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 09:13 +0000
Re: calling own methods from constructor Tobias Blass <tobiasblass@gmx.net> - 2011-04-07 10:58 +0000
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 12:19 +0000
Re: calling own methods from constructor Alessio Stalla <alessiostalla@gmail.com> - 2011-04-07 10:40 -0700
Re: calling own methods from constructor Tobias Blass <tobiasblass@gmx.net> - 2011-04-07 19:00 +0000
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 20:11 +0000
Re: calling own methods from constructor Jim Janney <jjanney@shell.xmission.com> - 2011-04-07 14:36 -0600
Re: calling own methods from constructor Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-04-07 20:59 -0400
Re: calling own methods from constructor Jim Janney <jjanney@shell.xmission.com> - 2011-04-07 10:26 -0600
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 20:16 +0000
Re: calling own methods from constructor Lew <lew@lewscanon.com> - 2011-04-07 14:05 -0700
Re: calling own methods from constructor Jim Janney <jjanney@shell.xmission.com> - 2011-04-07 16:15 -0600
Re: calling own methods from constructor Lew <noone@lewscanon.com> - 2011-04-07 21:28 -0400
Re: calling own methods from constructor Owen Jacobson <angrybaldguy@gmail.com> - 2011-04-07 23:21 -0400
Re: calling own methods from constructor Owen Jacobson <angrybaldguy@gmail.com> - 2011-04-07 23:39 -0400
Re: calling own methods from constructor Owen Jacobson <angrybaldguy@gmail.com> - 2011-04-07 23:58 -0400
Re: calling own methods from constructor Tom Anderson <twic@urchin.earth.li> - 2011-04-08 20:32 +0100
Re: calling own methods from constructor Tom Anderson <twic@urchin.earth.li> - 2011-04-07 23:05 +0100
Re: calling own methods from constructor Jim Janney <jjanney@shell.xmission.com> - 2011-04-07 17:38 -0600
Re: calling own methods from constructor Roedy Green <see_website@mindprod.com.invalid> - 2011-04-07 03:20 -0700
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-07 11:32 +0000
Re: calling own methods from constructor Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-04-08 01:51 +0200
Re: calling own methods from constructor Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-04-08 01:56 +0200
Re: calling own methods from constructor Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-04-08 09:30 +0000
Re: calling own methods from constructor Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-04-08 20:02 +0200
Page 1 of 3 [1] 2 3 Next page →
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-04-06 20:48 +0000 |
| Subject | calling own methods from constructor |
| Message-ID | <slrnippkd9.phi.avl@gamma.logic.tuwien.ac.at> |
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.
[toc] | [next] | [standalone]
| From | Tom Anderson <twic@urchin.earth.li> |
|---|---|
| Date | 2011-04-06 23:06 +0100 |
| Message-ID | <alpine.DEB.2.00.1104062255160.1512@urchin.earth.li> |
| In reply to | #2904 |
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
[toc] | [prev] | [next] | [standalone]
| From | Lew <noone@lewscanon.com> |
|---|---|
| Date | 2011-04-06 18:24 -0400 |
| Message-ID | <inip6r$l2n$1@news.albasani.net> |
| In reply to | #2906 |
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/wikipedia/commons/c/cf/Friz.jpg
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-04-07 08:44 +0000 |
| Message-ID | <slrnipqubm.phi.avl@gamma.logic.tuwien.ac.at> |
| In reply to | #2907 |
Lew <noone@lewscanon.com> 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...
[toc] | [prev] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2011-04-07 04:14 -0700 |
| Message-ID | <41ac2ca5-83e8-4b80-92af-9704b373ec37@q36g2000yqn.googlegroups.com> |
| In reply to | #2916 |
On 7 Apr., 10:44, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> Lew <no...@lewscanon.com> 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...
Well, that is clear, but: getClass() isn't a static method. Note that
Lew did not post the usual idiom with log4j and the like which
typically looks something like this:
private static final Logger logger = Logger.getLogger(Foo.class);
As for me, I can't remember having shot myself in the foot with this
feature of Java (i.e. allowing to invoke virtual methods in
constructor). I reckon, language designers figured that allowing it
is more worthwhile than preventing it. As Thomas pointed out you
would have to provide constructor arguments so subclasses can pass on
data they have created. This is tiresome and may even end up being
inefficient namely in the case where the superclass constructor needs
to decide which methods to call (or whether methods to call). You
would end up creating objects which then need to be discarded if the
super class constructor decides that he does not need them =>
inefficient code.
Btw, the check would be expensive for the compiler and I am also not
sure how that byte code might look like because you need to extend the
restrictions to all methods. Consider
class Foo {
private int v;
public Foo() {
v = init(); // allowed, because it's private
}
public void reinitialize() {
v = init();
}
private int init() {
// allowed, but only if init() is not invoked
// from a constructor:
int x = doSomething();
return x * 10 + 2;
}
/** Sub classes may override this.
* @return a number
*/
protected int doSomething() {
return 5;
}
}
Kind regards
robert
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-04-07 12:32 +0000 |
| Message-ID | <slrniprbm5.phi.avl@gamma.logic.tuwien.ac.at> |
| In reply to | #2923 |
Robert Klemme <shortcutter@googlemail.com> wrote:
> On 7 Apr., 10:44, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
> wrote:
>> Lew <no...@lewscanon.com> 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...
>
> Well, that is clear, but: getClass() isn't a static method.
Because getClass() is final, it didn't occur to me, that he
would have put up *that* as an example...
> As for me, I can't remember having shot myself in the foot with this
> feature of Java (i.e. allowing to invoke virtual methods in
> constructor). I reckon, language designers figured that allowing it
> is more worthwhile than preventing it. As Thomas pointed out you
> would have to provide constructor arguments so subclasses can pass on
> data they have created. This is tiresome and may even end up being
> inefficient namely in the case where the superclass constructor needs
> to decide which methods to call (or whether methods to call). You
> would end up creating objects which then need to be discarded if the
> super class constructor decides that he does not need them =>
> inefficient code.
The example of that Library class-hierarchy looked a bit
contrived to me.
> Btw, the check would be expensive for the compiler and I am also not
> sure how that byte code might look like because you need to extend the
> restrictions to all methods. [...]
It would be already an improvement, if direct calls to such
methods from the constructor were forbidden.
[toc] | [prev] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2011-04-07 05:55 -0700 |
| Message-ID | <13fe6a88-ce90-4a00-9801-50b1fad65251@d19g2000yql.googlegroups.com> |
| In reply to | #2930 |
On 7 Apr., 14:32, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> Robert Klemme <shortcut...@googlemail.com> wrote:
> > On 7 Apr., 10:44, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
> > wrote:
> >> Lew <no...@lewscanon.com> 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...
>
> > Well, that is clear, but: getClass() isn't a static method.
>
> Because getClass() is final, it didn't occur to me, that he
> would have put up *that* as an example...
Now there we have something *I* have overlooked. :-) I thought he had
picked it because getClass() always returns the actual class of the
instance regardless from which constructor it is invoked (other than
in C++) - but yes, it's probably not the perfect example.
> > As for me, I can't remember having shot myself in the foot with this
> > feature of Java (i.e. allowing to invoke virtual methods in
> > constructor). I reckon, language designers figured that allowing it
> > is more worthwhile than preventing it. As Thomas pointed out you
> > would have to provide constructor arguments so subclasses can pass on
> > data they have created. This is tiresome and may even end up being
> > inefficient namely in the case where the superclass constructor needs
> > to decide which methods to call (or whether methods to call). You
> > would end up creating objects which then need to be discarded if the
> > super class constructor decides that he does not need them =>
> > inefficient code.
>
> The example of that Library class-hierarchy looked a bit
> contrived to me.
>
> > Btw, the check would be expensive for the compiler and I am also not
> > sure how that byte code might look like because you need to extend the
> > restrictions to all methods. [...]
>
> It would be already an improvement, if direct calls to such
> methods from the constructor were forbidden.
I am not convinced. The risk seems rather low compared to the efforts
needed to implement your rule and the fact that now suddenly we get an
inconsistency: direct calls are forbidden while indirect calls are
allowed. Everybody needing this would instantaneously would start
swearing and a second later introduce a private method whose only
purpose is to delegate the call to the "forbidden" method. No, I
don't think this is a good idea. After all we are grown ups and
should take responsibility for the code we write. How often did you
shoot yourself in the foot because you are allowed to invoke sub class
methods from a constructor?
Cheers
robert
[toc] | [prev] | [next] | [standalone]
| From | Lew <lew@lewscanon.com> |
|---|---|
| Date | 2011-04-07 08:10 -0700 |
| Message-ID | <304a8aef-3852-4817-b5a7-5468fcdf11a1@x18g2000yqe.googlegroups.com> |
| In reply to | #2930 |
On Apr 7, 8:32 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> Robert Klemme <shortcut...@googlemail.com> wrote:
> > On 7 Apr., 10:44, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
> > wrote:
> >> Lew <no...@lewscanon.com> 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...
>
> > Well, that is clear, but: getClass() isn't a static method.
>
> Because getClass() is final, it didn't occur to me, that he
> would have put up *that* as an example...
>
Boy, you're spoiling for a fight, ain't'cha, sport?
It's final but it always returns the runtime class, so it is
overridden by the individual subtypes under the hood by special
compiler magic. Otherwise 'String#getClass()' would report type
'Object', which obviously it doesn't.
It presents the same kind of behavior as non-final overridable methods
for the purposes of this discussion.
You can use the same idiom using the "true Scotsman" definition of
overridability, just so we don't get sidetracked in a pointless
quibble. Hm-kaay?
(uncompiled:)
class Foo
{
private static final String FOOT = Foo.class.getSimpleName();
public String getFoot()
{
return FOOT;
}
private final String represent = "Insert "+ getFoot();
public String toString()
{
return represent;
}
}
class Bar extends Foo
{
private static final String BART = Bar.class.getSimpleName();
public String getFoot()
{
return BART;
}
}
--
Lew
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-04-07 20:31 +0000 |
| Message-ID | <slrnips7ou.phi.avl@gamma.logic.tuwien.ac.at> |
| In reply to | #2935 |
Lew <lew@lewscanon.com> wrote:
>> >> > Andreas Leitgeb wrote:
>> >> >>> Is there any *good* use of having the constructor call a method that
>> >> >>> actually *can* be overridden in a subclass? ...
>> >> > Foo() { [...] = [...] someStaticMethod ( getClass() ); [...] }
>> Because getClass() is final, it didn't occur to me, that he
>> would have put up *that* as an example...
> Boy, you're spoiling for a fight, ain't'cha, sport?
> It's final but it always returns the runtime class, so it is
> overridden by the individual subtypes under the hood by special
> compiler magic.
Actually, I tried to explain, why I was rambling about static methods
in response to your example.
Now, that you've made your point clearer, namely that getClass()
behaves like a virtual method overridden for *every* class, I even
understand it.
I'm just not yet convinced that this particular pattern, which is already
handled by JVM-magic (rather than by the compiler synthesizing those
virtual methods), would say "it's good to be able to call overridable
non-static methods from a constructor" sufficiently loudly. ;-)
[toc] | [prev] | [next] | [standalone]
| From | Lew <lew@lewscanon.com> |
|---|---|
| Date | 2011-04-07 14:10 -0700 |
| Message-ID | <0b2e25ae-35d6-45b6-8b8f-ac24d90f59ec@v8g2000yqb.googlegroups.com> |
| In reply to | #2943 |
Andreas Leitgeb wrote: > Actually, I tried to explain, why I was rambling about static methods > in response to your example. > No, you tried to be sarcastic and to make my answer seem wrong even though it was precisely what you asked for. > Now, that you've made your point clearer, namely that getClass() > behaves like a virtual method overridden for *every* class, I even > understand it. > And it even exactly fits the parameters of your original question. > I'm just not yet convinced that this particular pattern, which is already > handled by JVM-magic (rather than by the compiler synthesizing those > virtual methods), would say "it's good to be able to call overridable > non-static methods from a constructor" sufficiently loudly. ;-) I didn't ever say that it was good in such a general sense, thank you very much for shifting the context yet again. You asked if there were specific cases where it was good to use an overridable (you never said 'final' until you started pulling your "no true Scotsman" routine) method. I pointed out such. "Loudness" was not part of your request. It's just that there are occasionally (!) times when an overridable method (though not necessarily a 'final' one, since even 'final' methods can call overridable methods in turn) can be usefully called inside a constructor (or initializer, equivalently). That was the parameter of the original question, and that has been demonstrated. Twice over, now. -- Lew
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-04-07 22:15 +0000 |
| Message-ID | <slrnipsdr7.phi.avl@gamma.logic.tuwien.ac.at> |
| In reply to | #2947 |
Lew <lew@lewscanon.com> wrote: > Andreas Leitgeb wrote: >> Actually, I tried to explain, why I was rambling about static methods >> in response to your example. > No, you tried to be sarcastic and to make my answer seem wrong even > though it was precisely what you asked for. Without the explanation that you only gave later, it *was* wrong. I asked for an example of calling an overridable method from the constructor, and you gave an example where both a static and a final method got called. That that final method *could* have been instead implemented as a bunch of virtual methods, definitely wasn't obvious at that point. If you provide cryptic answers, just don't be surprised about them being misunderstood and therefore taken as non-answers. Until you explain them, that is. > You asked if there were specific cases where it was good to use an > overridable (you never said 'final' [...]) But 'final' surely implies non-overridability, doesn't it? Therefore, overridability of a method implies its non-'final'ity. > It's just that there are occasionally (!) times when an overridable > method (though not necessarily a 'final' one, since even 'final' > methods can call overridable methods in turn) can be usefully called > inside a constructor (or initializer, equivalently). That was the > parameter of the original question, and that has been demonstrated. > Twice over, now. 'kay
[toc] | [prev] | [next] | [standalone]
| From | Lew <noone@lewscanon.com> |
|---|---|
| Date | 2011-04-07 21:22 -0400 |
| Message-ID | <inlo0i$b9j$1@news.albasani.net> |
| In reply to | #2952 |
Andreas Leitgeb wrote: > Lew wrote: >> You asked if there were specific cases where it was good to use an >> overridable (you never said 'final' [...]) > But 'final' surely implies non-overridability, doesn't it? Therefore, > overridability of a method implies its non-'final'ity. Something used by 'getClass()' is overridden somewhere inside. Otherwise its behavior would not be what it is. Therefore there's an overridable method being called somewhere in the example I gave. Therefore it's a valid example. Give it a rest. First you wanted to excoriate the example for being 'static', which it wasn't. Then you wanted to excoriate it because the outer method is 'final', which is irrelevant. All along you had an example in front of you where it was useful to call an overridable method from a constructor, which is all that you asked for. You didn't (originally) ask that the method be called through a non-'final' method call. Instead you argued about points that had nothing to do with the example's validity or its utility. When you did add the rule that the call be directly to a non-'final' method, I promptly showed the equivalent example adhering to that new rule. What new rule are you going to add now, Mr. No True Scotsman? -- Lew Honi soit qui mal y pense. http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg
[toc] | [prev] | [next] | [standalone]
| From | Tom Anderson <twic@urchin.earth.li> |
|---|---|
| Date | 2011-04-07 23:08 +0100 |
| Message-ID | <alpine.DEB.2.00.1104072305290.25031@urchin.earth.li> |
| In reply to | #2935 |
[Multipart message — attachments visible in raw view] — view raw
On Thu, 7 Apr 2011, Lew wrote:
> On Apr 7, 8:32 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
> wrote:
>
>> Because getClass() is final, it didn't occur to me, that he would have
>> put up *that* as an example...
>
> Boy, you're spoiling for a fight, ain't'cha, sport?
>
> It's final but it always returns the runtime class, so it is overridden
> by the individual subtypes under the hood by special compiler magic.
What? No.
> Otherwise 'String#getClass()' would report type 'Object', which
> obviously it doesn't.
No. getClass() is final, not virtual, it is never overridden, and it does
not behave like it has been overridden. Rather, it behaves like its
implementation was:
public Class getClass() {
return this.class;
}
Where all objects have a secret magic hidden field called 'class' which is
set by the VM when they are allocated.
> It presents the same kind of behavior as non-final overridable methods
> for the purposes of this discussion.
It really doesn't. The problem with calling overridable methods from
constructors is that they can be overridden with code which assumes a
constructed object, and gets into trouble when run in the context of one
which isn't. getClass() can't get into that kind of trouble.
tom
--
Many of us adopted the File's slang as our own, feeling that we'd found a
tangible sign of the community of minds we'd half-guessed to be out there.
[toc] | [prev] | [next] | [standalone]
| From | Lew <noone@lewscanon.com> |
|---|---|
| Date | 2011-04-07 21:24 -0400 |
| Message-ID | <inlo39$b85$1@news.albasani.net> |
| In reply to | #2950 |
Tom Anderson wrote: >> It presents the same kind of behavior as non-final overridable methods for >> the purposes of this discussion. > > It really doesn't. The problem with calling overridable methods from > constructors is that they can be overridden with code which assumes a > constructed object, and gets into trouble when run in the context of one which > isn't. getClass() can't get into that kind of trouble. Fair enough. Good points. -- Lew Honi soit qui mal y pense. http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg
[toc] | [prev] | [next] | [standalone]
| From | "Mike Schilling" <mscottschilling@hotmail.com> |
|---|---|
| Date | 2011-04-09 22:06 -0700 |
| Message-ID | <inrdsc$qdd$1@dont-email.me> |
| In reply to | #2950 |
"Tom Anderson" <twic@urchin.earth.li> wrote in message
news:alpine.DEB.2.00.1104072305290.25031@urchin.earth.li...
>
> No. getClass() is final, not virtual, it is never overridden, and it does
> not behave like it has been overridden. Rather, it behaves like its
> implementation was:
>
> public Class getClass() {
> return this.class;
> }
>
> Where all objects have a secret magic hidden field called 'class' which is
> set by the VM when they are allocated.
That's how I've always thought about it, particularly since in 4GLs I've
helped implement, that's exactly what the analogous method did.
[toc] | [prev] | [next] | [standalone]
| From | Tom Anderson <twic@urchin.earth.li> |
|---|---|
| Date | 2011-04-07 23:10 +0100 |
| Message-ID | <alpine.DEB.2.00.1104072309110.25031@urchin.earth.li> |
| In reply to | #2930 |
On Thu, 7 Apr 2011, Andreas Leitgeb wrote: > Robert Klemme <shortcutter@googlemail.com> wrote: > >> As for me, I can't remember having shot myself in the foot with this >> feature of Java (i.e. allowing to invoke virtual methods in >> constructor). I reckon, language designers figured that allowing it is >> more worthwhile than preventing it. As Thomas pointed out you would >> have to provide constructor arguments so subclasses can pass on data >> they have created. This is tiresome and may even end up being >> inefficient namely in the case where the superclass constructor needs >> to decide which methods to call (or whether methods to call). You >> would end up creating objects which then need to be discarded if the >> super class constructor decides that he does not need them => >> inefficient code. > > The example of that Library class-hierarchy looked a bit > contrived to me. It was entirely contrived. I will keep an eye out for real code which does this, but i thought a timely answer was desirable! tom -- Many of us adopted the File's slang as our own, feeling that we'd found a tangible sign of the community of minds we'd half-guessed to be out there.
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-04-07 22:24 +0000 |
| Message-ID | <slrnipsedn.phi.avl@gamma.logic.tuwien.ac.at> |
| In reply to | #2951 |
Tom Anderson <twic@urchin.earth.li> wrote: >> The example of that Library class-hierarchy looked a bit >> contrived to me. > It was entirely contrived. :-) > I will keep an eye out for real code which does > this, I'd appreciate. > but i thought a timely answer was desirable! appreciated in hindsight :)
[toc] | [prev] | [next] | [standalone]
| From | Lew <noone@lewscanon.com> |
|---|---|
| Date | 2011-04-07 07:19 -0400 |
| Message-ID | <ink6j5$28p$1@news.albasani.net> |
| In reply to | #2916 |
On 04/07/2011 04:44 AM, Andreas Leitgeb wrote:
> Lew<noone@lewscanon.com> 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...
I did not realize that 'getClass()' was static.
--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg
[toc] | [prev] | [next] | [standalone]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2011-04-07 12:24 +0000 |
| Message-ID | <slrniprb7s.phi.avl@gamma.logic.tuwien.ac.at> |
| In reply to | #2924 |
Lew <noone@lewscanon.com> wrote: > On 04/07/2011 04:44 AM, Andreas Leitgeb wrote: >> Lew<noone@lewscanon.com> 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? >>> 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... > > I did not realize that 'getClass()' was static. I did not realize that getClass() was overidable - a property I even explicitly repeated in my question. For this, I assumed you were talking of getLogger().
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@ieee-dot-org.invalid> |
|---|---|
| Date | 2011-04-06 20:46 -0400 |
| Message-ID | <inj1mf$nu2$1@dont-email.me> |
| In reply to | #2906 |
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
esosman@ieee-dot-org.invalid
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.java.programmer
csiph-web