Methods
[Agent practical 3 of 9]
Now we'll build constructors for our Environment and Agent class. This is how we're going to tie our objects together so they can communicate.
Remember that with object variables, when we make the variable, we are just attaching a label to an object.
Environment world = new Environment();
With object variables, there's actually nothing to stop us attaching two labels to the same object:
Environment world = new Environment();
Environment grid = world;
It is the "new
" bit that is making the object, the
Environment world
and Environment grid
bits are just making
labels to attach to the new Environment()
object. This is different from
primitive variables, where a second label will be attached to a separate copy of the value in the
first variable.
Anyhow, why is this important now? It is important because it means there's nothing to stop us having labels in two classes pointing at the same object. We've seen it happen when we pass an object into a normal method and we're going to do it here with a constructor. We can use this to tie our objects together. If each of our Agents is going to contain their own behavioural code, we need some way for each to get hold of the Environment object. To set this up, we'd need to build the following (we've stripped out all the code not involved, so things are clearer -- you don't want to do this!):
--in Model.java----------------------------------------------------
public class Model {
--in Agent.java----------------------------------------------------
private Environment world = new Environment();
private Agent[] agents = new Agent[numberOfAgents];
public Model() {
for (int i = 0; i < agents.length; i++) {
agents[i] = new Agent(world); // Pass the Environment object to each Agent using Agent constructor.
}
}
}
public class Agent {
-------------------------------------------------------------------
private Environment world = null;
public Agent(Environment worldIn) { // Environment object picked up here.
world = worldIn;
}
}
Once this is implemented, every agent will have an instance variable label "world
" pointing at the
object passed into its constructor. In the case of every Agent this will be the same object, the object created by the line:
Environment world = new Environment();
in Model.java. Each agent can then use the "world
" label to access the object.
We've used the same label "world
" in both the Model and Agent classes, but it is important to realise they
are different labels as they are in different blocks/scope. The labels are different, despite using the same name and pointing at the same underlying object.
You can tell this because each class has the code to make the label:
Environment world = new Environment(); // In Model.java
Environment world = null; // In Agent.java
We could call the one in the Agent class "world4agents
" or something, but it is useful to get used to the
idea that the same name can be used for different labels in different scope and they aren't the same, even if they are also
pointing at the same object. As it happens, keeping it the same will also help with transfering the behaviour code.
Implement the above structure. It involves 1) in Agent, making an instance variable label set initially to null
;
2) in Agent, making a constructor that sets up this instance variable; and 3) in Model, passing the Environment object into
each Agent as it is made, using the new constructor. Remember not to delete the other useful code not explicitly given above.
As usual, compile and run your restructured model to check it works.
Once you've got that working, we'll go on to implementing the agent behaviour inside the agents.