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

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.

Diagram: UML


Once you've downloaded the two classes, go on to look at our new Agent interface.