Alright, I'll confess up front that I'm a neophyte when it comes to
designing Java programs, that's why I'm hoping for a little advice.
I'm designing an agent-based simulation program in which there is an
agent ('Agent' class) living within a world ('World' class) that
executes a certain pattern of movement ('Movement' class). The agent
will later be broken down into subtypes but for now that's not the
main focus.
I would like to keep the code for the movement completely separate
from the agent (i.e. no methods associated with movement in the agent
class, other than some form of call to an external procedure). I feel
like what I'd really like to do is multiply inherit, but I know that
Java doesn't support it. I looked into using an interface, but then
you have to define the implementation of the interface within the
class. So to me, that sounds like putting all of the code for the
movement in the agent class which is precisely what I didn't want to
do.
At the very least, I can create an instance of the movement class and
then run the methods of that instance, but seeing as I'm looking to
create thousands of agents, that will mean thousands of instances of
the movement class when really all I'm looking for is to run a
procedure. Does this really matter?
I'm sure there is probably a better solution out there, I just really
don't have a good perspective as to what it might be though.
Any advice on how to set things up in an orthodox way would be greatly
appreciated.
Thanks!
Eric Sosman - 13 Aug 2004 20:10 GMT
> Alright, I'll confess up front that I'm a neophyte when it comes to
> designing Java programs, that's why I'm hoping for a little advice.
[quoted text clipped - 26 lines]
> Any advice on how to set things up in an orthodox way would be greatly
> appreciated.
It sounds like each Agent should contain a reference
to the Movement that it uses. It seems likely that the
Movement methods will need access to some Agent-specific
state -- position, velocity, attitude, whatever -- which
suggests that you'll need one of two strategies:
1) Store the necessary state in the Movement object,
which means you'll need a dedicated Movement for
each Agent. But these "thousands of instances"
are not wasted, since you'd have needed to store
the Agent-specific state *somewhere* in any case.
2) Store the state in the Agent, and give the Agent
a reference to a Movement object that can be shared
with other Agents. This requires that the state
be passed back and forth between the Agent and the
Movement, which means either a standardized set of
state variables or some kind of MovementState wrapper
object for the variables a particular Movement cares
about -- and in the latter case, (1) seems simpler.
These approaches (and some others, most likely) can be
adapted and blended in lots of ways; the choice is not
strictly either/or.

Signature
Eric.Sosman@sun.com
thufir.hawat@mail.com - 14 Aug 2004 02:30 GMT
[..]
> I would like to keep the code for the movement completely separate
> from the agent (i.e. no methods associated with movement in the agent
[quoted text clipped - 5 lines]
> movement in the agent class which is precisely what I didn't want to
> do.
[..]
in your case, you say you "don't want to put the code in the agent class."
the short answer is: composition. whatever "all of the code" means,
that's your class. Maybe that code goes in Movement, maybe you make a
third class. I say, the more the merrier!
thus Agent will be composed of ClassX and Movement. to add functionality
to the Agent class, just create ClassY. when you look at the Agent class
it'll be easy on the eyes, hopefully, which is what you're after if i read
you right. the flip side is that you have to peek in ClassX to get to the
nuts and bolts, but that's a blessing in disguise since you now have
greater flexability. particularly were you to add additional packages,
any changes to the underlying code shouldn't have any ripple effect.
some general ideas surrounding inheritance and interfaces:
example and counter-example (not sure which is first), apologies to Head
First Java:
optical drive
/\
read write drive dvd drive
\/
dvd burner
the /\ forms a diamond shape, which head first java calls the "diamond of
\/
death", which causes the following problem:
ReadWriteDrive and DVDplayer extend OpticalDrive. Which one does
DVDburner extend? at least that's their argument, as i recall, against
multiple inheritance.
once multiple inheritance is ruled out as an option, that leads to asking
"why bother with an interface?" consider:
Mammal is abstract, Cat and Dog extend Mammal, hence inherits mammal
methods like giveBirth(), eat(), suckle(), etc. PetCat and PetDog
implement the Pet interface, which requires that these two classes
implement methods like beg(), trick(), etc. RoboDog isn't a Mammal, it
extends Robot perhaps, but it certainly can implement the Pet interface.
There's even an argument against using inheritance at all, composition may
be prefferable (Effective Java). in any event, the reason to use an
interface is increased robusteness. If down the road you try to remove
beg() from RoboDog or PetCat you'll get a compile error which beats a run
time error from something else which depended on the beg(), for instance.
Thufir Hawat
Bonhomme - 30 Aug 2004 14:29 GMT
Thanks to all who responded - you've helped to clarify things a lot! All the best,
Bonhomme