constructor inheritance/overriding?  
Author Message
bugbear





PostPosted: 2005-1-10 23:25:00 Top

java-programmer, constructor inheritance/overriding? If I have a base class with some over-loaded constructors
that perform significant work before calling the
"main" constructor, what is the best way of achieveing
the same set of constructors in a sub-class?

e.g.

class B {
B(A a) {
... lots of stuff ...
}
B(D d) {
this(get an A from the d);
}
B(S s) {
this(get an A from the s);
}
}

class E extends B {
E(A a) {
super(a);
addition 'E' specific code
}
}

How do I implement E(D d), and E(S s)?
As I understand things, constructors are not inherited (unlike C++),
so I do need an explicit implementation of each constructor. But the
"obvious" minimal implementation:
E(D d) {
super(d);
}
would call B(D d), which would then call B(A a).
Thus the extra 'E' specific code would NOT be called.
I don't (unless I must) want to expose the inner workings
of the other constructors in 'B', for reasons of data hiding
and code maintainance.

This question must have arisen before, but my googling failed
me.

Anyone have a solution?

BugBear
 
xarax





PostPosted: 2005-1-11 1:00:00 Top

java-programmer >> constructor inheritance/overriding? "bugbear" <email***@***.com> wrote in message
news:41e29e35$0$14613$email***@***.com...
> If I have a base class with some over-loaded constructors
> that perform significant work before calling the
> "main" constructor, what is the best way of achieveing
> the same set of constructors in a sub-class?
>
> e.g.
>
> class B {
> B(A a) {
> ... lots of stuff ...
> }
> B(D d) {
> this(get an A from the d);
> }
> B(S s) {
> this(get an A from the s);
> }
> }
>
> class E extends B {
> E(A a) {
> super(a);
> addition 'E' specific code
> }
> }
>
> How do I implement E(D d), and E(S s)?
> As I understand things, constructors are not inherited (unlike C++),
> so I do need an explicit implementation of each constructor. But the
> "obvious" minimal implementation:
> E(D d) {
> super(d);
> }
> would call B(D d), which would then call B(A a).

That is the correct way to do it.

> Thus the extra 'E' specific code would NOT be called.

WRONG. When super(a); returns, the remainder of the E(A a)
constructor is executed.

> I don't (unless I must) want to expose the inner workings
> of the other constructors in 'B', for reasons of data hiding
> and code maintainance.

That's good.

> This question must have arisen before, but my googling failed
> me.
>
> Anyone have a solution?

You already have your solution. Try it.


 
Andrea Desole





PostPosted: 2005-1-11 1:02:00 Top

java-programmer >> constructor inheritance/overriding? I'm not sure about what you mean, but I would say you should consider
putting the common code in some common methods in the class. So, first
thing I would say is to not call a constructor from another constructor.
I would rather do this:

class B
{
B( A a )
{
doALotOfStuff( a );
}

B( D d )
{
doALotOfStuff( d.getA() );
}

B( S s )
{
doALotOfStuff( s.getA() );
}

private void doALotOfStuff( A a )
{
// here you do your things
}
}

second, if you write the following:

E ( D d )
{
super( d );
// extra code
}

the extra code will be called. If you want to call the same code, just do:

E ( A a )
{
super( a );
doSomeSpecificThings();
}

E ( D d )
{
super( d );
doSomeSpecificThings();
}

Hope I got the point of the problem.


bugbear wrote:
> If I have a base class with some over-loaded constructors
> that perform significant work before calling the
> "main" constructor, what is the best way of achieveing
> the same set of constructors in a sub-class?
>
> e.g.
>
> class B {
> B(A a) {
> ... lots of stuff ...
> }
> B(D d) {
> this(get an A from the d);
> }
> B(S s) {
> this(get an A from the s);
> }
> }
>
> class E extends B {
> E(A a) {
> super(a);
> addition 'E' specific code
> }
> }
>
> How do I implement E(D d), and E(S s)?
> As I understand things, constructors are not inherited (unlike C++),
> so I do need an explicit implementation of each constructor. But the
> "obvious" minimal implementation:
> E(D d) {
> super(d);
> }
> would call B(D d), which would then call B(A a).
> Thus the extra 'E' specific code would NOT be called.
> I don't (unless I must) want to expose the inner workings
> of the other constructors in 'B', for reasons of data hiding
> and code maintainance.
>
> This question must have arisen before, but my googling failed
> me.
>
> Anyone have a solution?
>
> BugBear
 
 
Andrew McDonagh





PostPosted: 2005-1-11 6:35:00 Top

java-programmer >> constructor inheritance/overriding? Andrea Desole wrote:
> I'm not sure about what you mean, but I would say you should consider
> putting the common code in some common methods in the class. So, first
> thing I would say is to not call a constructor from another constructor.
> I would rather do this:
>
> class B
> {
> B( A a )
> {
> doALotOfStuff( a );
> }
>
> B( D d )
> {
> doALotOfStuff( d.getA() );
> }
>
> B( S s )
> {
> doALotOfStuff( s.getA() );
> }
>
> private void doALotOfStuff( A a )
> {
> // here you do your things
> }
> }

Yes, in fact the doALotOfStuff(...) method could actually be a private
constructor, then the call would be..

class B
{
B( A a )
{
this( a );
}

B( D d )
{
this( d.getA() );
}

B( S s )
{
this( s.getA() );
}

private B( A a)
{
// here you do your things
}
}

however...
>
> second, if you write the following:
>
> E ( D d )
> {
> super( d );
> // extra code
> }
>
> the extra code will be called. If you want to call the same code, just do:
>
> E ( A a )
> {
> super( a );
> doSomeSpecificThings();
> }
>
> E ( D d )
> {
> super( d );
> doSomeSpecificThings();
> }
>
> Hope I got the point of the problem.
>
>
> bugbear wrote:
>
>> If I have a base class with some over-loaded constructors
>> that perform significant work before calling the
>> "main" constructor, what is the best way of achieveing
>> the same set of constructors in a sub-class?
>>
>> e.g.
>>
>> class B {
>> B(A a) {
>> ... lots of stuff ...
>> }
>> B(D d) {
>> this(get an A from the d);
>> }
>> B(S s) {
>> this(get an A from the s);
>> }
>> }
>>
>> class E extends B {
>> E(A a) {
>> super(a);
>> addition 'E' specific code
>> }
>> }
>>
>> How do I implement E(D d), and E(S s)?
>> As I understand things, constructors are not inherited (unlike C++),
>> so I do need an explicit implementation of each constructor. But the
>> "obvious" minimal implementation:
>> E(D d) {
>> super(d);
>> }
>> would call B(D d), which would then call B(A a).
>> Thus the extra 'E' specific code would NOT be called.
>> I don't (unless I must) want to expose the inner workings
>> of the other constructors in 'B', for reasons of data hiding
>> and code maintainance.
>>
>> This question must have arisen before, but my googling failed
>> me.
>>
>> Anyone have a solution?
>>
>> BugBear

Good suggestions, another one for bugbear to consider, is that having so
many constructors can be a strong indication of multiple classes being
hidden within one large class.

Therefore, the answer may not be to worry about whether the right
constructor chain is called, but to worry about the class design.
 
 
Eric Sosman





PostPosted: 2005-1-11 6:58:00 Top

java-programmer >> constructor inheritance/overriding? Andrew McDonagh wrote:
>
> Yes, in fact the doALotOfStuff(...) method could actually be a private
> constructor, then the call would be..
>
> class B
> {
> B( A a )
> {
> this( a );
> }
>
> B( D d )
> {
> this( d.getA() );
> }
>
> B( S s )
> {
> this( s.getA() );
> }
>
> private B( A a)
> {
> // here you do your things
> }
> }

Are you sure about this? When I flesh this out with
classes A, D, and S, javac blurts out two errors:

B.java:15: B(A) is already defined in B
private B(A a) {
^

B.java:3: recursive constructor invocation
B(A a) {
^

That's with 1.4.2_04; have things changed in 1.5? I sure
hope not!

--
email***@***.com

 
 
Andrew McDonagh





PostPosted: 2005-1-11 7:22:00 Top

java-programmer >> constructor inheritance/overriding? Eric Sosman wrote:
> Andrew McDonagh wrote:
>
>>Yes, in fact the doALotOfStuff(...) method could actually be a private
>>constructor, then the call would be..
>>
>>class B
>>{
>> B( A a )
>> {
>> this( a );
>> }
>>
>> B( D d )
>> {
>> this( d.getA() );
>> }
>>
>> B( S s )
>> {
>> this( s.getA() );
>> }
>>
>> private B( A a)
>> {
>> // here you do your things
>> }
>> }
>
>
> Are you sure about this? When I flesh this out with
> classes A, D, and S, javac blurts out two errors:
>
> B.java:15: B(A) is already defined in B
> private B(A a) {
> ^
>
> B.java:3: recursive constructor invocation
> B(A a) {
> ^
>
> That's with 1.4.2_04; have things changed in 1.5? I sure
> hope not!
>

oh, I missed that the first constructor took an instance of A, and
therefore looks the same as the private constructor.

However, it just means remove the private constructor and the two other
constructors will call the first (public) constructor directly.

One question though, if all that the extra constructors are doing is

this(x.getA())

where x is either an instance of D or S, then why have these
constructors at all?

Why can't the calling code do the getA() call leaving the B class just
having one constructor?

i.e.

B b = new B(d.getA());

or

B b = new B(s.getA());

If its because this code is sprinkled around the code base, and the
constructors are just a way of removing this duplication, then we could
approach that problem another way, whilst still having only one
constructor on the B class.

Like using an interface to decouple the getA() method from any
particular Type, as in...

class B
{
B( AContainer anAContainer )
{
A a = anAContainer.getA();
....
}
}


interface AContainer
{
A getA();
}


class A implements AContainer
{
a getA()
{
return this;
}
}


class D implements AContainer
{
a getA()
{
return this.a;
}
}

class S implements AContainer
{
a getA()
{
return this.a;
}
}


 
 
bugbear





PostPosted: 2005-1-11 17:49:00 Top

java-programmer >> constructor inheritance/overriding? xarax wrote:
> "bugbear" <email***@***.com> wrote in message

(see thread for code sample)

>>
>>How do I implement E(D d), and E(S s)?
>>As I understand things, constructors are not inherited (unlike C++),
>>so I do need an explicit implementation of each constructor. But the
>>"obvious" minimal implementation:
>>E(D d) {
>> super(d);
>>}
>>would call B(D d), which would then call B(A a).
>
>
> That is the correct way to do it.
>
>
>>Thus the extra 'E' specific code would NOT be called.
>
>
> WRONG. When super(a); returns, the remainder of the E(A a)
> constructor is executed.

If we were in E.E(A a) that is obviously true.
But how did we get into (the start of) E.E(A a)?
Which method (contructor in this case) called it?

BugBear
 
 
bugbear





PostPosted: 2005-1-11 17:52:00 Top

java-programmer >> constructor inheritance/overriding? Andrew McDonagh wrote:
> Andrea Desole wrote:
>
>> I'm not sure about what you mean, but I would say you should consider
>> putting the common code in some common methods in the class. So, first
>> thing I would say is to not call a constructor from another
>> constructor.

This is a possible solution. but constructors have some
special properties that other methods don't have w.r.t
"final" fields.

http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#35962

BugBear
 
 
bugbear





PostPosted: 2005-1-11 18:01:00 Top

java-programmer >> constructor inheritance/overriding? Andrea Desole wrote:
> I'm not sure about what you mean, but I would say you should consider
> putting the common code in some common methods in the class. So, first
> thing I would say is to not call a constructor from another constructor.
> I would rather do this:

The (generic) problem I'm trying to address is this;
I have a base class with multiple (overloaded) constructors.
Some of these constructors call each other, to avoid
code duplication.

My question is how do I create a sub-class with the same
overloaded constructors with (again) minimal code
duplication?

My best solution so far has been to create a method called
void _constructor(A a)
which is (like all methods other than constructors) dispatched dynamically.
With E._constructor(A a) calling super._constructor(a), everything thing works
almost as desired.

E.E(D d) simply calls super(d) i.e. B.B(D d).
This calls _constructor(A a), which is dynamically dispatched
as E.E(A a), so everything works. The key limitation is that
_constructor cannot assign to a "final" field, so this useful
language tool is now forbidden to me.

So I would like a "better" solution than mine.

BugBear
 
 
Chris Uppal





PostPosted: 2005-1-11 18:39:00 Top

java-programmer >> constructor inheritance/overriding? bugbear wrote:

> If I have a base class with some over-loaded constructors
> that perform significant work before calling the
> "main" constructor, what is the best way of achieveing
> the same set of constructors in a sub-class?

A different approach would be to put most of the initialisation work into
"normal", overridable methods called from the constructors.

================
class B
{
B(A a) { initialize(a); }
B(D d) { initialize(get an A from the d); }
B(S s) { initialize(get an A from the s); }

protected void intialize(A a)
{
... lots of stuff...
}
}

class E extends B
{
E(A a) { super(a); } // stupid duplication, but that's Java for
you...
E(D d) { super(d); }
E(S s) { super(s); } // ...end of stupid duplication

protected void intialize(A a)
{
super.initialize(a);
... addition 'E' specific code ...
}
}

================


If you find the idea of calling overridden methods from the constructor
insupportable (some people seem to, a POV I feel less and less inclined to
agree the more I think about it), then you can package the constructors up into
factory methods which also invoke the overridden initialisation methods.
Unfortunately, since the factory methods don't override, you'll end up with
more mechanical duplication than you would otherwise need.

-- chris


 
 
Andrea Desole





PostPosted: 2005-1-11 18:41:00 Top

java-programmer >> constructor inheritance/overriding?
>
> E.E(D d) simply calls super(d) i.e. B.B(D d).
> This calls _constructor(A a), which is dynamically dispatched
> as E.E(A a), so everything works. The key limitation is that
> _constructor cannot assign to a "final" field, so this useful
> language tool is now forbidden to me.

oh, there are some finals. I would still hope that, if you call a method
from a constructor, and that mehod initializes some final members, you
are still in the constructor, so it should be possible to do that.
Probably it's not allowed because you can call that method from any
place in the code.

>
> So I would like a "better" solution than mine.

Well, if you want to initialize some final members in the derived class,
and this is not possible if not from the constructor, and you want to
avoid code duplication, that looks a bit more difficult.
How about putting your finals in a separate class, which is in turn a
member of your original class? In that way the only code duplication in
your constructors would be just the creation of the class. You still
have to access the member class every time, but it looks to me a fair
solution.
I would like to know if I'm missing something here.
 
 
John C. Bollinger





PostPosted: 2005-1-11 21:54:00 Top

java-programmer >> constructor inheritance/overriding? Andrea Desole wrote:

> Well, if you want to initialize some final members in the derived class,
> and this is not possible if not from the constructor, and you want to
> avoid code duplication, that looks a bit more difficult.
> How about putting your finals in a separate class, which is in turn a
> member of your original class? In that way the only code duplication in
> your constructors would be just the creation of the class. You still
> have to access the member class every time, but it looks to me a fair
> solution.

I was about to suggest something along the same lines. If a class or
class hierarchy is complex enough that it is difficult to implement
appropriate constructors then it is high time to refactor. Moving some
of the members and associated initialization into separate classes is a
powerful and useful refactoring that may go a long way toward solving
this very type of problem. When applied appropriately it can also
simplify the class hierarchy and clarify class responsibilities.

Another possible alternative is to assign complex class initialization
responsibilities to a separate factory class. Such a factory could not
directly initialize final members of the target classes, but that is
what those classes' constructors are for. A factory class can perform
calculations of arbitrary complexity in order to determine the values
that final members of the constructed class ought to have, however. If
necessary, factory classes can extend other factory classes, which is
one way around the fact that Java constructors are not virtual.


John Bollinger
email***@***.com
 
 
P.Hill





PostPosted: 2005-1-12 6:06:00 Top

java-programmer >> constructor inheritance/overriding? bugbear wrote:
>
> The (generic) problem I'm trying to address is this;
> I have a base class with multiple (overloaded) constructors.
> Some of these constructors call each other, to avoid
> code duplication.
>
> My question is how do I create a sub-class with the same
> overloaded constructors with (again) minimal code
> duplication?

Hmm, this is very curious. What problem do the finals solve that can't
be solved by controlling their access view private declarations on the
members and some of their access methods?

I guess I'm leaning toward search for some refactoring also.

-Paul
 
 
P.Hill





PostPosted: 2005-1-12 6:06:00 Top

java-programmer >> constructor inheritance/overriding? bugbear wrote:
>
> The (generic) problem I'm trying to address is this;
> I have a base class with multiple (overloaded) constructors.
> Some of these constructors call each other, to avoid
> code duplication.
>
> My question is how do I create a sub-class with the same
> overloaded constructors with (again) minimal code
> duplication?

Hmm, this is very curious. What problem do the finals solve that can't
be solved by controlling their access view private declarations on the
members and some of their access methods?

I guess I'm leaning toward search for some refactoring also.

-Paul