/** Here we define all the attributes and operations that every animal will * have. Other specialized classes for different types of animals will * build on this basic definition. * The classifier "protected" means that these attributes can be accessed * in this file, and in subclasses, but nowhere else. * * By the way, I've included print statements in the constructors just so * we can see what's going on. In the long run, we usually wouldn't do this. */ public class Animal { protected double weight; protected boolean isWarmBlooded; protected boolean isHungry; public Animal() { weight = 10; isWarmBlooded = false; isHungry = true; System.out.println("Just created an animal."); } public String toString() { return "animal"; } /** An animal should only exercise if it's had enough to eat (if not hungry). * We also have special cases for fish and birds. * Here in the Animal class we can look down and see if an Animal object is * a Fish or a Bird, but we can't call any specific Fish or Bird function. * without using a cast. Another alternative is to write separate * exercise() versions in Bird and the other subclasses as desired. */ public void exercise() { if (isHungry) System.out.println("Too hungry to exercise, sorry."); else { if (this instanceof Fish) System.out.println(this + " swims about!"); else if (this instanceof Bird && ((Bird)this).canFly()) System.out.println("watch " + this + " fly!"); else System.out.println(this + " gets a workout!"); isHungry = true; } } /** Only feed the animals if they are really hungry. */ public void feed() { if (! isHungry) System.out.println(this + " isn't hungry at the moment. Try later."); else { System.out.println(this + " is grateful for the grub!"); weight += 0.1; isHungry = false; } } public double getWeight() { return weight; } }