constructor inheritance/overriding?

B

bugbear

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
 
X

xarax

bugbear said:
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.
 
A

Andrea Desole

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.
 
A

Andrew McDonagh

Andrea said:
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.

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.
 
E

Eric Sosman

Andrew said:
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!
 
A

Andrew McDonagh

Eric said:
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;
}
}
 
B

bugbear

xarax said:
"bugbear" <bugbear@trim_papermule_trim.co.uk> wrote in message

(see thread for code sample)
That is the correct way to do it.




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
 
B

bugbear

Andrea said:
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
 
C

Chris Uppal

bugbear said:
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
 
A

Andrea Desole

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.
 
J

John C. Bollinger

Andrea said:
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
(e-mail address removed)
 
P

P.Hill

bugbear said:
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

P.Hill

bugbear said:
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
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top