A common way to do this is by use of a static class. This is essentially a class where everything is static, so you don't make any instances of this class. In this case, you would probably want a "garden" class to keep track of all of your plants. Assuming you don't plan on having multiple gardens, this will be the garden class for your application, which is why it makes sense for it to be a static class. In order to keep track of all the plants, the garden class will need to contain your "field of plants" array, and in order to be useful, it needs to implement some utility methods to access that array. Here is how I would implement the garden class:
// Notice the final modifier. This is standard for static classes because there is
// no point in extending them.
public final class Garden {
// Here's your "field of plants" array. Notice it's static, so its not bound to
// any instance.
private static final Plant[][] FIELD_OF_PLANTS = new Plant[100][100];
// Notice the private constructor. This is also standard for static classes
// because there is no point in initializing them, since everything is static.
private Garden() { }
// This is a utility method to get the location of a given plant. It just does a
// linear search through the array and returns the location when it finds a match.
// You can find much faster algorithms, but for demonstration purposes, linear
// search does the job.
public static Point getPlantLocation(Plant plant) {
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
if (FIELD_OF_PLANTS[i][j] == plant) {
return new Point(i, j);
}
}
}
// If we got this far, that means plant isn't anywhere in FIELD_OF_PLANTS
throw new NoSuchElementException();
}
// This is a utility method going the other way, finding which plant is at a given
// location. It just returns the proper index in the array.
public static Plant getPlantAt(int x, int y) {
return FIELD_OF_PLANTS[x][y];
}
// This is a mutator utility method for planting a plant in the garden.
// It just sets the appropriate index of the array to the passed in plant object.
public static void setPlantAt(int x, int y, Plant plant) {
FIELD_OF_PLANTS[x][y] = plant;
}
}
Then in your plant class, you can just get rid of the location information, and you can still add methods that use the location of the plant:
public class Plant {
// Notice the only thing the plant knows is its type and size.
private int size;
private final String plantType;
public Plant(String ptype, int s) {
plantType = ptype;
size = s;
}
// This method uses the plant's location by calling the static class' utility
// method.
public void printAllInformation() {
Point location = Garden.getPlantLocation(this);
System.out.format("I am a %s and my size is %d. I am at row %d, column %d.%n",
plantType, size, location.y, location.x);
}
}
You can test all of this using a simple driver class like so:
public class Driver {
public static void main(String args[]) {
FIELD_OF_PLANTS[12][14] = new Plant("noodle plant", 0);
FIELD_OF_PLANTS[12][14].printAllInformation();
}
}
The result should be:
I am a noodle plant and my size is 0. I am at row 14, column 12.
This way you've only stored the location of each plant once, in your garden class, but each plant can still figure out where it is in the garden.