영어로 읽는 코딩

49_[자바] 다형성

The following example puts it a slightly different way. First, let’s create a reusable library of Shape types:

 

//: polymorphism/shape/Shape.java
package polymorphism.shape;
public class Shape {
    public void draw() {}
	public void erase() {}
} ///:~
//: polymorphism/shape/Circle.java
package polymorphism.shape;
import static net.mindview.util.Print.*;
public class Circle extends Shape {
	public void draw() { print("Circle.draw()"); }
	public void erase() { print("Circle.erase()"); }
} ///:~
//: polymorphism/shape/Square.java
package polymorphism.shape;
import static net.mindview.util.Print.*;
public class Square extends Shape {
	public void draw() { print("Square.draw()"); }
	public void erase() { print("Square.erase()"); }
} ///:~
//: polymorphism/shape/Triangle.java
package polymorphism.shape;
import static net.mindview.util.Print.*;
public class Triangle extends Shape {
	public void draw() { print("Triangle.draw()"); }
	public void erase() { print("Triangle.erase()"); }
} ///:~
//: polymorphism/shape/RandomShapeGenerator.java
// A "factory" that randomly creates shapes.
package polymorphism.shape;
import java.util.*;
public class RandomShapeGenerator {
	private Random rand = new Random(47);
	public Shape next() {
		switch(rand.nextInt(3)) {
			default:
			case 0: return new Circle();
			case 1: return new Square();
			case 2: return new Triangle();
		}
	}
} ///:~
//: polymorphism/Shapes.java
// Polymorphism in Java.
import polymorphism.shape.*;
public class Shapes {
	private static RandomShapeGenerator gen =
		new RandomShapeGenerator();
	public static void main(String[] args) {
		Shape[] s = new Shape[9];
	// Fill up the array with shapes:
		for(int i = 0; i < s.length; i++)
			s[i] = gen.next();
	// Make polymorphic method calls:
		for(Shape shp : s)
		shp.draw();
}
} /* Output:
Triangle.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Circle.draw()
*///:~

The base class Shape establishes the common interface to anything inherited from Shape—that is, all shapes can be drawn and erased. The derived classes override these definitions to provide unique behavior for each specific type of shape.

RandomShapeGenerator is a kind of “factory” that produces a reference to a randomly-selected Shape object each time you call its next( ) method. Note that the upcasting happens in the return statements, each of which takes a reference to a Circle, Square, or Triangle and sends it out of next( ) as the return type, Shape. So whenever you call next( ), you never get a chance to see what specific type it is, since you always get back a plain Shape reference.

main( ) contains an array of Shape references filled through calls to RandomShapeGenerator.next( ). At this point you know you have Shapes, but you don’t know anything more specific than that (and neither does the compiler). However, when you step through this array and call draw( ) for each one, the correct type-specific behavior magically occurs, as you can see from the output when you run the program.

The point of creating the shapes randomly is to drive home the understanding that the compiler can have no special knowledge that allows it to make the correct calls at compile time. All the calls to draw( ) must be made through dynamic binding.

 

 

[Thinking in Java, 198]

댓글

댓글 본문
버전 관리
Yoo Moon Il
현재 버전
선택 버전
graphittie 자세히 보기