Two inheritence hierachies are associated - Cast or Hide ?

V

VisionSet

Person-------->Dog
^ ^
| |
Male--------->ButchDog

Person has a Dog
Male has a ButchDog

If I want to call the Dog types from the Person types polymorphically is it
best style to cast for each call or hide the Dog type with the ButchDog type
in Male with an instance variable eg:

public class A {

X z;

public A(X x) {
z = x;
}

public void doStuff1()
z.stuff();
}
}

class B extends A {

Y z;

public B(Y y) {
super(y);
z = y;
}

public void doStuff2()
z.stuff();
}

}

class X {
public void stuff() {}
}

class Y extends X {
public void stuff() {}
}

// OR...

public class A {

X z;

public A(X x) {
z = x;
}

public void doStuff1()
z.stuff();
}
}

class B extends A {

public B(Y y) {
super(y);
}

public void doStuff2()
((Y) z).stuff();
}

}

TIA
 
J

John C. Bollinger

VisionSet said:
Person-------->Dog
^ ^
| |
Male--------->ButchDog

Person has a Dog
Male has a ButchDog

If I want to call the Dog types from the Person types polymorphically is it
best style to cast for each call or hide the Dog type with the ButchDog type
in Male with an instance variable eg:

Neither. If Dog is polymorphic with respect to the method(s) you want
to invoke then you don't have to cast or store multiple references, nor
do you have to create different methods on Person and Male. Just invoke
the polymorphic method via Person's reference to the relevant Dog,
without caring what _kind_ of Dog it might be. That's the essence of
polymorphism. See example below.
public class A {

X z;

public A(X x) {
z = x;
}

public void doStuff1()
z.stuff();
}
}

So far, so good.
class B extends A {

Y z;

Ack! Don't do this. Hiding an instance variable is messy and
confusing. Hiding it with a differently-typed reference to the same
object is just ugly.
public B(Y y) {
super(y);
z = y;
}

public void doStuff2()
z.stuff();
}

This is pointless. If b is a reference to an instance of B, then
b.doStuff1() has exactly the same result as b.doStuff2().
}

class X {
public void stuff() {}
}

class Y extends X {
public void stuff() {}
}

// OR...

public class A {

X z;

public A(X x) {
z = x;
}

public void doStuff1()
z.stuff();
}
}

class B extends A {

public B(Y y) {
super(y);
}

public void doStuff2()
((Y) z).stuff();
}

As before, if b is a B, then b.doStuff1() has exactly the same effect as
b.doStuff2(). You would only need to cast if you wanted to invoke a
method Y.stuff2(), defined for Y but not for X.

You're making it all too hard. Try this on for size (using definitions
above for X and Y):

public class A {

X z;

public A(X x) {
z = x;
}

public void doStuff()
z.stuff();
}
}

class B extends A {
public B(Y y) {
super(y);
}

// no other code needed
}


John Bollinger
(e-mail address removed)
 
V

VisionSet

Ack! Don't do this. Hiding an instance variable is messy and
confusing. Hiding it with a differently-typed reference to the same
object is just ugly.

Suspected so.
You're making it all too hard. Try this on for size (using definitions
above for X and Y):

public class A {

X z;

public A(X x) {
z = x;
}

public void doStuff()
z.stuff();
}
}

class B extends A {
public B(Y y) {
super(y);
}

// no other code needed
}

You've missed my point, probably my fault.
The point is that there is not an overridden doStuff() (hence the doStuff 1
& 2). I want to call subclass (Y) specific methods from B. So I do need to
cast or keep reference to the subclass somewhere.

I realise the polymorphic ripple you have illustrated.
 
J

John C. Bollinger

VisionSet said:
Ack! Don't do this. Hiding an instance variable is messy and
confusing. Hiding it with a differently-typed reference to the same
object is just ugly.


Suspected so.
[...]

You've missed my point, probably my fault.
The point is that there is not an overridden doStuff() (hence the doStuff 1
& 2). I want to call subclass (Y) specific methods from B. So I do need to
cast or keep reference to the subclass somewhere.

Ah, I see. I was confused by the use of "stuff" to refer to both a
general X method and a (distinct) Y-specific one. In that case, cast.
If you like, you can create a method to do it for you (e.g. ButchDog
getDogAsButchDog()); that might be particularly appealing if you are
already self-encapsulating anyway, and/or if you don't want class A to
expose its member variable directly.


John Bollinger
(e-mail address removed)
 
V

VisionSet

In that case, cast.
If you like, you can create a method to do it for you (e.g. ButchDog
getDogAsButchDog()); that might be particularly appealing if you are
already self-encapsulating anyway, and/or if you don't want class A to
expose its member variable directly.

Perfect, thanks!
 
V

VisionSet

If you like, you can create a method to do it for you (e.g. ButchDog
getDogAsButchDog()); that might be particularly appealing if you are
already self-encapsulating anyway, and/or if you don't want class A to
expose its member variable directly.

Actually, something else...

This is all very well when you have a class to put method body in to do the
cast but if you have interfaces you end up with this sort of thing:

interface Dog {

Bone getBone();
}

interface ButchDog extends Dog {

ButchBone getButchBone();
}

ButchBone being a subclass of Bone

I suspect Tiger addresses this, but how would you address it otherwise,
since ButchDog is now a confusing interface.
 
X

xarax

VisionSet said:
Actually, something else...

This is all very well when you have a class to put method body in to do the
cast but if you have interfaces you end up with this sort of thing:

interface Dog {

Bone getBone();
}

interface ButchDog extends Dog {

ButchBone getButchBone();
}

ButchBone being a subclass of Bone

I suspect Tiger addresses this, but how would you address it otherwise,
since ButchDog is now a confusing interface.

I have no problem with interface hierarchies. The
above hierarchy appears quite often in my applications.
Mostly for extending the Iterator interface:

public interface FubarIterator
extends Iterator
{
public abstract Fubar nextFubar();
}

public abstract class FubarIteratorAbstract
implements FubarIterator
{
public Fubar nextFubar()
{
return /* the next Fubar instance */;
}

public Object next()
{
return nextFubar();
}

/* All of the other stuff needed for implementation. */
}

The Iterator interface has a method next() that
returns Object. I use the subinterface to return
the specific type that I want from the Iterator.
The design greatly reduces casts appearing in
the application. The casts are hidden behind the
interface methods. In the above example, the
implementation of the next() method of Iterator
simply passes the call to nextFubar().

Generics (J2SE 5.0) may help to alleviate the casts
for most of the Collections interfaces and classes.
I would only use generics where it helps readability
and understandability, because the compiler inserts
invisible casts. Casts can clutter the source code,
but they make it plainly clear what is the programmer's
intent.

Two cents worth. Your mileage may vary.
 
J

John C. Bollinger

VisionSet said:
Actually, something else...

This is all very well when you have a class to put method body in to do the
cast but if you have interfaces you end up with this sort of thing:

interface Dog {

Bone getBone();
}

interface ButchDog extends Dog {

ButchBone getButchBone();
}

ButchBone being a subclass of Bone

I don't personally find the interface case any more confusing than the
class case. YMMV.


John Bollinger
(e-mail address removed)
 

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
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top