阅前声明: http://blog.csdn.net/heimaoxiaozi/archive/2007/01/19/1487884.aspx
Exercise 1
/****************** Exercise 1 ***************** * Add a new method in the base class of * Shapes.java that prints a message, but don't * override it in the derived classes. Explain * what happens. Now override it in one of the * derived classes but not the others, and see * what happens. Finally, override it in all the * derived classes. ***********************************************/ class Shape { void draw() {} void erase() {} void print() { System.out.println("Base-class print()"); } } class Circle extends Shape { void draw() { System.out.println("Circle.draw()"); } void erase() { System.out.println("Circle.erase()"); } void print() { System.out.println("Circle.print()"); } } class Square extends Shape { void draw() { System.out.println("Square.draw()"); } void erase() { System.out.println("Square.erase()"); } void print() { System.out.println("Square.print()"); } } class Triangle extends Shape { void draw() { System.out.println("Triangle.draw()"); } void erase() { System.out.println("Triangle.erase()"); } void print() { System.out.println("Triangle.print()"); } } public class E01_NewShapeMethod { public static void main(String args[]) { Shape[] s = { new Circle(), new Square(), new Triangle(), }; // Make polymorphic method calls: for(int i = 0; i < s.length; i++) { s[i].draw(); s[i].erase(); s[i].print(); } } } //+M java E01_NewShapeMethod **The above code is the final version, with print( ) overriden in all classes. **With print( ) defined only in the base class, the output is: Circle.draw() Circle.erase() Base-class print() Square.draw() Square.erase() Base-class print() Triangle.draw() Triangle.erase() Base-class print() ** Since the base-class version is not being overridden, it is used everywhere. **With print( ) overridden in Circle, the output is: Circle.draw() Circle.erase() Circle.print() Square.draw() Square.erase() Base-class print() Triangle.draw() Triangle.erase() Base-class print() **The overridden version is used in Circle, and the default base-class version is used everywhere else. **If print( ) is overridden everywhere, the result is: Circle.draw() Circle.erase() Circle.print() Square.draw() Square.erase() Square.print() Triangle.draw() Triangle.erase() Triangle.print() **Thus, the overriden version will always be used if it is available. Exercise 2 /****************** Exercise 2 ***************** * Add a new type of Shape to Shapes.java and * verify in main() that polymorphism works for * your new type as it does in the old types. ***********************************************/ class Tetrahedron extends Shape { void draw() { System.out.println("Tetrahedron.draw()"); } void erase() { System.out.println("Tetrahedron.erase()"); } void print() { System.out.println("Tetrahedron.print()"); } } public class E02_NewShapeType { public static void main(String args[]) { Shape[] s = { new Circle(), new Square(), new Triangle(), new Tetrahedron() }; // Make polymorphic method calls: for(int i = 0; i < s.length; i++) { s[i].draw(); s[i].erase(); s[i].print(); } } } //+M java E02_NewShapeType **Since the other shape definitions are in the same directory (default package) we can just add the new shape and override the methods. The code in the for loop is unchanged from the previous example. The output is: Circle.draw() Circle.erase() Circle.print() Square.draw() Square.erase() Square.print() Triangle.draw() Triangle.erase() Triangle.print() Tetrahedron.draw() Tetrahedron.erase() Tetrahedron.print() Exercise 3 /****************** Exercise 16 ***************** * Change Music3.java so that what() becomes the * root Object method toString(). Try printing * the Instrument objects using * System.out.println() (without any casting). ***********************************************/ class Instrument { public void play() { System.out.println("Instrument.play()"); } public String toString() { return "Instrument"; } public void adjust() {} } class Wind extends Instrument { public void play() { System.out.println("Wind.play()"); } public String toString() { return "Wind"; } public void adjust() {} } class Percussion extends Instrument { public void play() { System.out.println("Percussion.play()"); } public String toString() { return "Percussion"; } public void adjust() {} } class Stringed extends Instrument { public void play() { System.out.println("Stringed.play()"); } public String toString() { return "Stringed"; } public void adjust() {} } class Brass extends Wind { public void play() { System.out.println("Brass.play()"); } public void adjust() { System.out.println("Brass.adjust()"); } } class Woodwind extends Wind { public void play() { System.out.println("Woodwind.play()"); } public String toString() { return "Woodwind"; } } public class E03_MusicToString { static Instrument[] orchestra = { new Wind(), new Percussion(), new Stringed(), new Brass(), new Woodwind() }; public static void printAll(Instrument[] orch){ for(int i = 0; i < orch.length; i++) System.out.println(orch[i]); } public static void main(String args[]) { printAll(orchestra); } } //+M java E03_MusicToString **The output is: Wind Percussion Stringed Wind Woodwind Exercise 4 /****************** Exercise 4 ***************** * Add a new type of Instrument to Music3.java * and verify that polymorphism works for your * new type. ***********************************************/ class Electronic extends Instrument { public void play() { System.out.println("Electronic.play()"); } public String toString() { return "Electronic"; } public void adjust() {} } public class E04_NewInstrument { static Instrument[] orchestra = { new Wind(), new Percussion(), new Stringed(), new Brass(), new Woodwind(), new Electronic() }; public static void main(String args[]) { for(int i = 0; i < orchestra.length; i++) { orchestra[i].play(); orchestra[i].adjust(); System.out.println(orchestra[i]); } } } //+M java E04_NewInstrument **The output is: Wind.play() Wind Percussion.play() Percussion Stringed.play() Stringed Brass.play() Brass.adjust() Wind Woodwind.play() Woodwind Electronic.play() Electronic Exercise 5 /****************** Exercise 5 ***************** * Modify Music3.java so that it randomly creates * Instrument objects the way Shapes.java does. ***********************************************/ class InstrumentGenerator { public Instrument next() { switch((int) (Math.random() * 6)) { default: case 0: return new Wind(); case 1: return new Percussion(); case 2: return new Stringed(); case 3: return new Brass(); case 4: return new Woodwind(); case 5: return new Electronic(); } } } public class E05_RandomInstruments { public static void main(String args[]) { InstrumentGenerator gen = new InstrumentGenerator(); for(int i = 0; i < 20; i++) System.out.println(gen.next()); } } //+M java E05_RandomInstruments **The idea of a generator is a common one. Every time you call it, it produces a new value, but when you call it you don’t give it any parameters. **One of the flaws with this design is managing the case statement, which is a bit awkward an error-prone. It would be much nicer if we could just index into an array of objects that could themselves generate the different kinds of instruments. This is possible if we use some features of the Class object. Here’s the more elegant solution (that I didn’t expect you to get!): // A more sophisticated solution using features // you'll learn about in later chapters. class InstrumentGenerator2 { Class instruments[] = { Wind.class, Percussion.class, Stringed.class, Brass.class, Woodwind.class, Electronic.class, }; java.util.Random gen = new java.util.Random(); public Instrument next() { try { int idx = Math.abs(gen.nextInt()) % instruments.length; return (Instrument) instruments[idx] .newInstance(); } catch(Exception e) { System.out.println("e = " + e); throw new RuntimeException( "Cannot Create Instrument"); } } } public class E05_RandomInstruments2 { public static void main(String args[]) { InstrumentGenerator2 gen = new InstrumentGenerator2(); for(int i = 0; i < 20; i++) System.out.println(gen.next()); } } //+M java E05_RandomInstruments **References to Class objects for each type of instrument can be produced using the .class that you see in the array. The random number generator method nextInt( ) produces positive and negative numbers covering all 32 bits of an int, so it must be forced to be absolute, and the modulus operator will put it in the range of the array. Class objects have a method newInstance( ) which will create objects of their particular class, but these will throw exceptions. Here, I print the exception but then create and throw a RuntimeException (you’ll learn about exceptions in chapter 10) because I consider it a programming error that doesn’t need to be caught at compile-time. **Note the benefit of this design – if you need to add a new type to the system, you only need to add it in the Class array; everywhere else takes care of itself. Exercise 6 /****************** Exercise 6 ***************** * Create an inheritance hierarchy of Rodent: * Mouse, Gerbil, Hamster, etc. In the base * class, provide methods that are common to all * Rodents, and override these in the derived * classes to perform different behaviors * depending on the specific type of Rodent. * Create an array of Rodent, fill it with * different specific types of Rodents, and call * your base-class methods to see what happens. ***********************************************/ class Rodent { public void hop() { System.out.println("Rodent hopping"); } public void scurry() { System.out.println("Rodent scurrying"); } public void reproduce() { System.out.println("Making more Rodents"); } public String toString() { return "Rodent"; } } class Mouse extends Rodent { public void hop() { System.out.println("Mouse hopping"); } public void scurry() { System.out.println("Mouse scurrying"); } public void reproduce() { System.out.println("Making more Mice"); } public String toString() { return "Mouse"; } } class Gerbil extends Rodent { public void hop() { System.out.println("Gerbil hopping"); } public void scurry() { System.out.println("Gerbil scurrying"); } public void reproduce() { System.out.println("Making more Gerbils"); } public String toString() { return "Gerbil"; } } class Hamster extends Rodent { public void hop() { System.out.println("Hamster hopping"); } public void scurry() { System.out.println("Hamster scurrying"); } public void reproduce() { System.out.println("Making more Hamsters"); } public String toString() { return "Hamster"; } } public class E06_Rodents { public static void main(String args[]) { Rodent[] rodents = { new Mouse(), new Gerbil(), new Hamster(), }; for(int i = 0; i < rodents.length; i++) { rodents[i].hop(); rodents[i].scurry(); rodents[i].reproduce(); System.out.println(rodents[i]); } } } //+M java E06_Rodents **The output is: Mouse hopping Mouse scurrying Making more Mice Mouse Gerbil hopping Gerbil scurrying Making more Gerbils Gerbil Hamster hopping Hamster scurrying Making more Hamsters Hamster Exercise 7 /****************** Exercise 7 ***************** * Modify Exercise 6 so that Rodent is an * abstract class. Make the methods of Rodent * abstract whenever possible. ***********************************************/ abstract class Rodent2 { public abstract void hop(); public abstract void scurry(); public abstract void reproduce(); } class Mouse2 extends Rodent2 { public void hop() { System.out.println("Mouse hopping"); } public void scurry() { System.out.println("Mouse scurrying"); } public void reproduce() { System.out.println("Making more Mice"); } public String toString() { return "Mouse"; } } class Gerbil2 extends Rodent2 { public void hop() { System.out.println("Gerbil hopping"); } public void scurry() { System.out.println("Gerbil scurrying"); } public void reproduce() { System.out.println("Making more Gerbils"); } public String toString() { return "Gerbil"; } } class Hamster2 extends Rodent2 { public void hop() { System.out.println("Hamster hopping"); } public void scurry() { System.out.println("Hamster scurrying"); } public void reproduce() { System.out.println("Making more Hamsters"); } public String toString() { return "Hamster"; } } public class E07_AbstractRodent { public static void main(String args[]) { Rodent2[] rodents = { new Mouse2(), new Gerbil2(), new Hamster2(), }; for(int i = 0; i < rodents.length; i++) { rodents[i].hop(); rodents[i].scurry(); rodents[i].reproduce(); System.out.println(rodents[i]); } } } //+M java E07_AbstractRodent **This produces the same output as the previous example. Note that toString( ) is a method of the root class Object and thus can be left out of the abstract base class.