Inheritance
[Agent practical 4 of 9]
This practical we're going to step back from developing our model for a bit, and thing about its longer term use. We'll restructure it a bit to make it flexible and more future-proof. We'll then add some agent-to-agent communication.
Start by making a new directory: java\src\unpackaged\framework4\ -- however, there's no need to copy last practical's code in because we're going to give you the code in this practical; in part so you can concentrate on what's going on, and in part so everyone has a copy of the code which definitely works the same way.
At the moment all our agent-based code is in one class, Agent
. This is ok, but what if we decide we want several different agents?
Having all our agent code in Agent means that if we want to add a different agent class, Predator
for example, not only are we now left with "Predators vs. Agents",
which seems odd, but we have to double-up all the generic code that might be useful in both classes. It would be much better if we structured our agent code
in a hierarchy of types, and place the more generic code in the more generic classes.
In addition, it would be nice if we could develop code that called the "run
" method on all the different classes of agent without worrying
which they are. If we had a generic interface "Agent
" that just defined a run method existed, we could store any type of agent in an array of
type Agent
.
Let's now solve these two issues by restructuring our code into an inheritance hierarchy, thus:
The hierarchy is designed to do two things. The first is that it allows us to have a generic Agent
array in Model. Because the array will be
defined to hold anything matching the Agent
interface, we will be able to call run()
, getX()
, and getY()
on
whatever is in the array without worrying about what kind of implementation of Agent
each object is. In short, the interface will
generically define agents that run and that report their
position in space.
Note that from now on we'll be careful to distinquish Agents (capital "A") that match this interface, and agents (small "a") that are just a generic name for an object with agency within an Agent-Based Model (capitalised anyhow).
The second thing the hierarchy is designed for is so that we can keep all the actual code for reporting on an agent in space in the Animal
superclass. Animal will
implement Agent
, and allow us to generate multiple subclasses of agent that report their position in space without always having to
replicate the basic code to do so. As it happens, here we'll only have one subclass: Nibbler
, which will implement our specific behaviour -- in our
case moving around and nibbling (eating small chunks of) the Environment. If we wanted to implement a Predator
class we'd just subclass Animal for that
as well, but, as it happens, for this course we'll stick with Nibblers -- we're friendly like that.
Rather than getting you to develop these yourself, we'll give you them, with a commentary, a file at a time. We'll start with the interface and then move to the most generic code, in Animal, before looking at what is left for our Nibblers to do. As we go through, try to get a clear idea of where behaviour is implemented.
First up, here's our Model and Environment classes.
As you'll see, changing Agent
to an interface doesn't change either class at all, save one small change in
Model.java: rather than making Agent
objects, we now make Nibbler
s.
See the comments in Model.java
for details of why there are so few changes.
Once you understand why the Model class isn't massively affected, copy both classes into your java\src\unpackaged\framework4\ directory.