abstract class Animal { String name; // The human name for the animal, not some secret animal name. String sound; // What sound does it vocalize? /** Constructor. * @param _name the name of the animal. * @param _sound what sound the animal makes. */ Animal( String _name, String _sound ) { this.name = _name; this.sound = _sound; } /** When the animal wants to bug a human, it says... * @return The sound of the animal, bugging its owner. */ public String speak() { return this.name + ": " + this.sound + ", " + this.sound + "."; } /** Test: overriding "speak". */ public static void test2() { System.out.println( "====" ); System.out.println( "Testing Inheritance:" ); System.out.println( new Cat("Bartok").speak() ); System.out.println( new Dog("Beethoven").wagTail() ); System.out.println( new Dog("Phydeaux").speak() ); System.out.println( new Python().speak() ); } /** Test: polymorphism. */ public static void test3() { System.out.println( "====" ); System.out.println( "Testing polymorphism: " ); Animal[] zoo = { new Cat("Bartok"), new Dog("Beethoven"), new Dog("Phydeaux"), new Python() }; // Demonstrate polymorphism: // In the loop, "critter" is of (declared) type Animal, // yet Dog's specialized speak() is still getting used. // System.out.println( "Polymorphism:" ); for ( Animal critter : zoo ) { System.out.println( critter.speak() ); } /* equivalent to the above for-each loop: for (int i=0; i < zoo.length; ++i ) { Animal critter; critter = zoo[i]; System.out.println( critter.speak() ); } */ } String communicateHunger() { return this.speak() + this.speak() + this.speak() + "!"; } }