|
View:
New views
2 Messages
—
Rating Filter:
Alert me
|
|
|
Allowing super() calls to come later in subclass constructorsHi all,
I have a question regarding the requirement for constructor calls to be the first statement from other constructors. If I'm asking in the wrong place, please correct me and I apologize in advance. I considered carefully before emailing, but I found no other discussion areas which get into this level of detail or have the experience I expect to find here. My question boils down to: Why is it forbidden to perform local (i.e. stack or non-instance) operations prior to calling a constructor? Is this an enhancement worth making? Currently, the first call in any subclass constructor must be a call to the super constructor (or the implicit super()) or a call to another constructor. I would like to present a case where this is inconvenient at the least and encourages poor workarounds. Consider the following situation that has no difficulties. A is a class which takes as an argument another nontrivial object. B is a subclass which intends to abstract away the complexity of A's argument. The example is oversimplified - imagine the compoundThing is sufficiently complicated to create and it is useful to abstract it away for a special case (namely, B). class A{ A( ArgType compoundThing) {... } } class B extends A{ B( OtherType one, OtherType two ) { super ( new ArgType(one, two, "constantThree") ) } } This works great. Now suppose that B wants to hold on to the argument which it passes to super(). It seems like it should be able to, since it had created the object to begin with. Ideally we'd just say foo = new ArgType(...) and then super(foo) but this isn't permitted. So we can do this... class B extends A{ B( OtherType one, OtherType two) { this(new ArgType(one, two, "constantThree") } private B (ArgType compoundThing){ super(compoundThing) Object foo = compoundThing } } In order to keep a handle to the object that I created in the constructor, I have to create an entirely new constructor so that it is stored on the stack as an argument. That looks like poor form. Now suppose I also want to do input validation on B's arguments prior to calling the constructor. Ideally I'd just want to do this before calling super(...) but I could do this instead... class B extends A{ B ( OtherType one, OtherType two){ this(one, two, B.checkArgs(one, two)) } private B (OtherType one, OtherType two, Object ignore){ super( new ArgType(one, two, "constantThree") ) } static Object checkArgs(OtherType one, OtherType two){ if(one==null || two==null) throw new IllegalArgumentException() return null } } Now I've created a new constructor AND a static method that, in my opinion, are useless. If I combined this with the above solution, I'd have 2 extra constructors and a static method where I'd rather just have: class B extends A{ B ( OtherType one, OtherType two){ if(one==null || two==null) throw new IllegalArgumentException() Object foo = new ArgType(one, two, "constantThree") super(foo) } } I think I've demonstrated that anything you want to do without touching `this` or `super` prior to calling a constructor can be accomplished through these ugly workarounds. Is it not reasonable to allow these operations to precede the constructor calls? Thanks, Derrick P.S. I'm sorry that this email was so long, but I wanted to clearly demonstrate that this would be syntactic sugar and how it's absence can lead to some very poor looking code. I hope it has been a worthwhile read and thank you for your patience. |
|
|
Re: Allowing super() calls to come later in subclass constructorsIn addition to the things you've shown are allowed, the VM specification allows the code to assign to fields of "this" before the superclass constructor. That's necessary in some cases to generate correct code for inner classes.
The only difficulty with your proposal is that writing the specification to describe exactly what can and cannot be done in that code (and implementing it) will be cumbersome. For example, does the superclass constructor invocation have to be at the top level, or can it be nested within an "if" statement (with a possibly different one within the else clause)? Is this worth the effort, when that effort could be put elsewhere? Cheers, Neal On Mon, Nov 9, 2009 at 3:41 PM, Derrick Rice <derrick.rice@...> wrote: Hi all, |
| Free embeddable forum powered by Nabble | Forum Help |