public class OldMcDonald {
	private Animal[] _farm; // Old McDonald had a farm (still has now)
	private static final int SIZE = 3; // Fixed farm size

	public OldMcDonald() {
		_farm = new Animal [SIZE];
		_farm[0] = new Animal("Cow", "Moo");
		_farm[1] = new Animal("Dog", "Woof");
		_farm[2] = new Animal("Duck", "Quack");
	}

	public void sing() {
		for (int i = 0; i < SIZE; i++)
			System.out.println("Old McDonald had a farm, E-I-E-I-O\n" +
			                   "And on his farm he had a " + _farm[i].getName() + ", E-I-E-I-O\n" +
			                   "With a " + _farm[i].getSound() + " " + _farm[i].getSound() + " here and a " +
			                   _farm[i].getSound() + " " + _farm[i].getSound() + " there...\n"
			                   );
	}

	public static void main(String[] args) {
		(new OldMcDonald()).sing();

		/* The above is an example of an anonymous object instantiation.
		   Alternatively, you may create a reference omd to refer to the
		   newly created OldMcDonald object, like this:

		      OldMcDonald omd = new OldMcDonald();
		      omd.sing();

		   However, since this reference omd is used only once to call the
		   method sing() and never again, we can save creating this explicit 
		   reference omd and use anonymous object instantiation instead.
		 */
	}
}

class Animal {
	private String _name; // e.g. Cow
	private String _sound; // e.g. Moo
	public Animal(String name, String sound) {
		_name = name;
		_sound = sound;
	}
	public String getName() {
		return _name;
	}
	public String getSound() {
		return _sound;
	}
}
