Java equivalent of MI for augmenting base of a hierarchy

D

David Bolen

I was wondering what might be a typical approach in Java to handle a
case where I might have used multiple inheritance in languages that
supported it; specifically that of wanting to augment a base class and
its child classes without having to replicate code in the child
classes.

In the simplest case, let's say that I have a simple hierarchy like:

Player
|
Dealer

Now I come along and I wish to have an augmented Player class, say one
that is cognizant of a GUI subsystem. So what I'd like to end up with
is, conceptually, a new hierarchy of:

Player
|
+----+----+
| |
Dealer GUIPlayer
| |
+----+----+
|
GUIDealer

In an MI language, I would just inherit from both GUIPlayer and Dealer
and I'd have my GUIDealer - likely without writing any actual body
code in GUIDealer.

In Java, its simple enough for GUIPlayer to extend Player, but
obviously I can't MI from Dealer. And since Dealer is a concrete
class I can't use it as an interface. Even if I were to extract
Dealer into an interface (which would get me the equivalence I might
want with respect to method parameters) I'd still have to implement
the interface twice, in Dealer and GUIDealer, even though the
implementations would be identical.

At the moment I'm looking at doing delegation with an internal Dealer
object inside of GUIDealer. It still requires that I ensure I keep
GUIDealer manually in sync with the Dealer interface (so extracting
Dealer to an interface would make that easier to ensure in an
automated way), but I have to keep writing the code to delegate each
method.

Is there a more Java-centric way to handle this sort of problem?

Thanks.

-- David
 
J

James Wilson

David said:
I was wondering what might be a typical approach in Java to handle a
case where I might have used multiple inheritance in languages that
supported it; specifically that of wanting to augment a base class and
its child classes without having to replicate code in the child
classes.

In the simplest case, let's say that I have a simple hierarchy like:

Player
|
Dealer

Now I come along and I wish to have an augmented Player class, say one
that is cognizant of a GUI subsystem. So what I'd like to end up with
is, conceptually, a new hierarchy of:

Player
|
+----+----+
| |
Dealer GUIPlayer
| |
+----+----+
|
GUIDealer

In an MI language, I would just inherit from both GUIPlayer and Dealer
and I'd have my GUIDealer - likely without writing any actual body
code in GUIDealer.

In Java, its simple enough for GUIPlayer to extend Player, but
obviously I can't MI from Dealer. And since Dealer is a concrete
class I can't use it as an interface. Even if I were to extract
Dealer into an interface (which would get me the equivalence I might
want with respect to method parameters) I'd still have to implement
the interface twice, in Dealer and GUIDealer, even though the
implementations would be identical.

At the moment I'm looking at doing delegation with an internal Dealer
object inside of GUIDealer. It still requires that I ensure I keep
GUIDealer manually in sync with the Dealer interface (so extracting
Dealer to an interface would make that easier to ensure in an
automated way), but I have to keep writing the code to delegate each
method.

Read "Effective Java Progamming Language Guide" by Joshua Block. Item's
14, 16, 17, 34 speek specifically to your questions.
Is there a more Java-centric way to handle this sort of problem?

Thanks.

-- David
I think you're on the right track though. Composition is a good way.

public interface Player
methods of the interface

public interface Dealer extends Player
extra methods of the interface

public interface GUIPlayer extends Player
extra methods of the interface

public interface GUIDealer extends Dealer, GUIPlayer
extra methods of the interface


And then create concrete implementations of each of these
interfaces.

Hope this helps,

James
 
D

David Bolen

James Wilson said:
I think you're on the right track though. Composition is a good way.

public interface Player
methods of the interface

public interface Dealer extends Player
extra methods of the interface

public interface GUIPlayer extends Player
extra methods of the interface

public interface GUIDealer extends Dealer, GUIPlayer
extra methods of the interface


And then create concrete implementations of each of these
interfaces.

Yeah, that's what I figured - unfortunately in this example I
duplicate even more effort (implementations) than just single
inheriting from GUIPlayer in that I have to duplicate both the
GUIPlayer and Dealer logic in GUIDealer. If I inherit from GUIPlayer
than I just have to reimplement the original Dealer/Player logic
differences.

The rub is that the only practical between GUIDealer and Dealer is the
difference created between GUIPlayer and Player - so other than
wanting to inherit that difference, any other code I write as part of
GUIDealer is duplication that I have to maintain.

Thanks for the info (and book reference) though.

-- David
 
J

John C. Bollinger

David said:
Yeah, that's what I figured - unfortunately in this example I
duplicate even more effort (implementations) than just single
inheriting from GUIPlayer in that I have to duplicate both the
GUIPlayer and Dealer logic in GUIDealer. If I inherit from GUIPlayer
than I just have to reimplement the original Dealer/Player logic
differences.

The rub is that the only practical between GUIDealer and Dealer is the
difference created between GUIPlayer and Player - so other than
wanting to inherit that difference, any other code I write as part of
GUIDealer is duplication that I have to maintain.

I came late to this discussion, so likely I'm missing something, but it
sure seems like Dealer is a role that a Player can have more than it is
a specific type of Player. The design is more loosely coupled if Dealer
does not extend Player but instead is associated with a Player. Among
the advantages this would provide is that there would be no need for
different kinds of Dealers in parallel with different kinds of Players
(i.e. you could do away with GUIDealer altogether).

Also, interfaces are very useful in many situations, but not so useful
if there is no room for alternative implementations. In this particular
case, if Player is a class then it can expose a package-private API for
a seperate Dealer object to use, but if it is an interface then all its
methods are implictly public.


John Bollinger
(e-mail address removed)
 
D

David Bolen

John C. Bollinger said:
I came late to this discussion, so likely I'm missing something, but
it sure seems like Dealer is a role that a Player can have more than
it is a specific type of Player. The design is more loosely coupled
if Dealer does not extend Player but instead is associated with a
Player. Among the advantages this would provide is that there would
be no need for different kinds of Dealers in parallel with different
kinds of Players (i.e. you could do away with GUIDealer altogether).

As with any design, I'd have to agree that there are multiple ways to
build the original class hierarchy, but I did find it more natural to
consider Dealer to have a fairly classic "is a" relationship with
Player. A Dealer is just another form of a Player which overrides
some characteristics (such as presentation of hand). I suppose I
could have encapsulated presentation of hand into a separate role sort
of object, but then I end up with two tightly coupled object
effectively needing to share state (the hand) which otherwise just
belongs to the Player. I guess I could argue either way though. The
net is still though that I only burped in the Java implementation due
to lack of MI (of implementation).

I do have additional Rules and Behavior classes that function in more
of a role design, where any player object can be associated with
(composed of) rules that it obeys and with behavior that it exhibits
in reacting to events/queries. But Dealer felt more natural as a
subclass in the original (pre-GUI) implementation.
Also, interfaces are very useful in many situations, but not so useful
if there is no room for alternative implementations. In this
particular case, if Player is a class then it can expose a
package-private API for a seperate Dealer object to use, but if it is
an interface then all its methods are implictly public.

All its methods, or just those methods that are needed to meet the
interface? Presumably Player could implement the interface, but still
offer other package-private API methods for use by other objects, right?

-- David
 

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,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top