calling own methods from constructor

  • Thread starter Andreas Leitgeb
  • Start date
L

Lew

Andreas said:
Lew said:
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?
 
L

Lew

Tom said:
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.
 
L

Lew

Jim said:
Lew writes:
Consider focussing on what I did say, instead of what it sort of sounds
like I might have said. The solution is in the paragraph above, the one
that starts with "In effect, until the constructor of Foo completes".

Dude, I was just asking for explanation of something I admitted I did not
understand, and gave you what I admitted I understood to be a misimpression
already. I didn't quote everything you said because I naturally assumed you
knew what you'd said and would understand if I have just enough context to
establish my question. I guess not.

Sah-ree!
 
O

Owen Jacobson

Lew, bog off.
In the message I was replying to, in the text that you deleted, Owen
Jacobsen correctly observed that

Jacobson. Like the UML guy, to my eternal mortification. :)
This is a technical issue, and I observed that other languages have
found ways to prevent virtual methods from being called before their
owning objects have been fully constructed. One can debate whether this
desirable, but C++ provides an existence proof that it's possible.

Sure. C++'s objection initialization proceeds from the top down, just
like Java's, with the difference that the class of '*this' changes as
constructors complete. In your extension of my example, with

public class Foo { /* ... */ }

public class Bar extends Foo { /* ... */ }

this would mean that during Foo's constructor, 'this' points to a Foo
object, while during Bar's constructor, it points to a Bar object*.
However, in Java, constructor chaining is syntactically a statement, so
it appears that control flow begins in the most-derived class's
constructor before chaining upwards through each superclass's
constructor to Object() -- and that's exactly what happens under the
hood!

$ cat Surprise.java
class Surprise {
public Surprise(String s) {
super(); // explicit for the sake of discussion only.
}
}

class Subprise extends Surprise {
public Subprise() {
super("Hello, world!");
}
}

$ javap -classpath . Subprise -c
Compiled from "Surprise.java"
class Subprise extends Surprise{
public Subprise();
Code:
0: aload_0
1: ldc #1; //String Hello, world!
3: invokespecial #2; //Method Surprise."<init>":(Ljava/lang/String;)V
6: return

}

Given that JVM-level implementation of constructors, having the class
of 'this' change after the third instruction would be very tricky to
implement. C++ doesn't have this problem, since (a) constructor
chaining is NOT syntactically like a statement and (b) constructor
chaining doesn't have to compile like one, either.

Could it have been designed differently? Sure. Java's constructor
semantics are a weird-but-mostly-intuitive mix of C++'s constructors
and Smalltalk's initializers-are-just-methods approach (where you're
not forced to chain to a parent class's initializer at all). It's a
compromise, and like all compromises, it's not quite like any of the
alternatives; however, I think having the type of 'this' remain stable
is a useful feature. :)

-o

* And also that if Foo.Foo() captures 'this' in a field, Bar.Bar() can
compare this to the field using == and get true back, even though the
class has changed. 'new' is only allowed to introduce one distinct new
pointer.
 
A

Andreas Leitgeb

Daniele Futtorovic said:
class BaseClass implements [...] {

In principle this is the same kind of example as Tom's.

It has already been established by now, that this calling
of virtual methods from the c'tor *can* be used with caution
such that it doesn't necessarily lead to bugs.
Also, that alternatives exist, even though they may appear
to be less convenient at times.

What's left open and would interest me is, if this pattern is
already used in any of the big Java-based projects. E.g. a publically
accessible javadoc of the API of a lib documenting some protected
method to be "called from some superclass constructor and thus
the implementation should not assume 'this' instance to be
initialized to any degree."

Not that this existence or non-existence would have any real
impact on Java's future, of course...
 
D

Daniele Futtorovic

Daniele Futtorovic said:
class BaseClass implements [...] {

In principle this is the same kind of example as Tom's.

No. In Tom's example, the subclass provided functionality to the
superclass. In my example, the subclass adds to what the superclass does.

I also presented that example to illustrate how implementing the
Externalizable contract can impact the issue. Because Externalizable
mandates a no-arg c'tor, some mechanisms one might have used in similar
cases cannot be used there.
 
T

Tom Anderson

Could it have been designed differently? Sure. Java's constructor
semantics are a weird-but-mostly-intuitive mix of C++'s constructors and
Smalltalk's initializers-are-just-methods approach (where you're not
forced to chain to a parent class's initializer at all).

Since we're talking other languages, i'll mention Python, where in a
typical chained constructor:

class Subprise(Surprise):
def __init__(self):
super(Subprise, self).__init__()

not only is the call to the superclass __init__ method a perfectly normal
call, so is the use of super()!

tom
 
M

Mike Schilling

Tom Anderson said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top