1. 다형성(polymorphism)

- 여러가지 형태를 가질 수 있는 능력.

- 하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것.

- 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하는 것.

- 조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있지만, 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수 없다.

- 참조변수의 타입이 참조변수가 참조하고 있는 객체에서 사용할 수 있는 멤버의 개수를 결정한다.



2. 참조변수의 형변환

- 서로 상속관계에 있는 타입간의 형변환만 가능하다.

- 자손타입 => 조상타입 (Up-casting) : 형변환 생략가능

- 조상타입 => 자손타입 (Down-casting) : 형변환 생략불가

- 바로 윗 조상이나 자손이 아닌 간접적인 상속관계 경우에도 형변환이 가능하다.

- 형변환을 수행하기 전에 instanceof 연산자를 사용해서 인스턴스 타입을 확인하는 것이 안전하다.

class Car {
	String color;
	int door;
	
	void drive() {
		System.out.println("운전 합니다. 부릉부릉");
	} // drive : 운전하는 메서드
	
	void stop() {
		System.out.println("정지합니다. 끼이이익");
	} // stop : 정지하는 메서드
} // Car

class FireEngineCar extends Car {
	void water() {
		System.out.println("물 뿌립니다.");
	} // water : 물뿌리는 메서드
} // FireEngineCar extends Car

public class Cating {

	public static void main(String[] args) {
		Car car = null; // Car 클래스 타입의 참조변수 car 선언하고  null 로 초기화
		FireEngineCar fireEngineCar = new FireEngineCar(); // FireEngineCar 클래스 타입의 참조변수 fireEngineCar 선언, FireEngineCar 인스턴스 생성
		FireEngineCar fireEngineCar2 = null; // FireEngineCar 클래스 타입의 참조변수 fireEngineCar 선언하고 null 로 초기화
		
		fireEngineCar.water();
		car = fireEngineCar; // car = (Car) fe; 자손 => 조상 형변환은 생략가능
	//	car.water(); Car 타입의 참조변수로는 자식클래스인 FireEngineCar의 water() 메서드를 호출 할 수 없다.
		
		fireEngineCar2 = (FireEngineCar) car; // 조상 => 자손 형변환
		fireEngineCar2.water();
		
	} // main
} // Cating

/*
 * 결과
 * 
 * 물 뿌립니다.
 * 물 뿌립니다.
 */

3. instanceof 연산자

- 참조변수가 참조하는 인스턴스의 실제  타입을 알아보기 위해 사용한다.

- 왼쪽에는 참조변수, 오른쪽에는 참조형 변수와 타입, 연산결과는 true, false 하나를 반환한다. (null인 참조변수는 false 결과를 얻는다)

- instanceof 결과가 true 이면, 해당 타입으로 형변환이 가능하다.

class Car {
	
} // Car

class FireEngine extends Car {
	
} // FireEngine extends Car

public class InstanceofTest {
	public static void main(String[] args) {
		FireEngine fireEngine = new FireEngine();
		
		if(fireEngine instanceof FireEngine) {
			System.out.println("FireEngine 인스턴스");
		}
		
		if(fireEngine instanceof Car) {
			System.out.println("Car 인스턴스");
		}
		
		if(fireEngine instanceof Object) {
			System.out.println("Object 인스턴스");
		}
	} // main
} // InstanceofTest

/*
 * 결과
 * 
 * FireEngine 인스턴스
 * Car 인스턴스
 * Object 인스턴스
 */

4. 참조변수와 인스턴스의 연결

- 멤버변수가 중복정의된 경우, 참조변수의 타입에 따라 연결되는 멤버변수가 달라진다.

- 메서드가 중복정의된 경우, 참조변수의 타입에 관계없이 항상 실제 인스턴스(오바라이딩된 메서드)의 타입에 정의된 메서드가 호출된다.

class Parent {
	int z = 100;
	
	void method() {
		System.out.println("부모 메서드");
	}
} // Parent

class Child extends Parent {
	int z = 200;
	
	void method() {
		System.out.println("z = " + z); // this.z 와 같다.
		System.out.println("super.z = " + super.z);
		System.out.println("this.z = " + this.z);
	}
} // Child extends Parent

public class BindingTest {
	public static void main(String[] args) {
		Parent parent = new Child();
		Child child = new Child();
		
		System.out.println("parent.z = " + parent.z); // 인스턴스 변수인 z는 참조변수의 타입에 따라서 달라진다.
		parent.method(); // Child 인스턴스를 참조하기 때문에 Child의 메서드가 실행된다.
		
		System.out.println();
		
		System.out.println("child.z = " + child.z); // 인스턴스 변수인 z는 참조변수의 타입에 따라서 달라진다.
		child.method(); // Child 인스턴스를 참조하기 때문에 Child의 메서드가 실행된다.
	} // main
} // BindingTest

5. 매개변수의 다형성

- 참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

class Product {
	int price, bonusPoint;
	
	public Product(int price) {
		this.price = price;
		bonusPoint = (int) (price / 10.0); // 보너스 점수는 제품가격의 10%
	} // Product todtjdwk
} // Product

class Tv extends Product {
	Tv() {
		super(100); // 조상클래스의 생성자 Product(int price)를 호출
	}
	
	public String toString() {
		return "TV";
	}
} // Tv extends Product

class Computer extends Product {
	public Computer() {
		super(200);
	}
	
	public String toString() {
		return "Computer";
	}
} // Computer extends Product

class Buyer {				
	int money = 1000; // 소유 금액
	int bonusPoint = 0; // 보너스 포인트
	
	void buy(Product p) {
		if(money < p.price) {
			System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
			return;
		} // if
		
		money -= p.price;
		bonusPoint += p.bonusPoint;
		System.out.println(p + " 을 / 를 구입하셨습니다.");
	}
} // Buyer
public class PolyArgumentTest {
	public static void main(String[] args) {
		Buyer buyer = new Buyer();
		Tv tv = new Tv();
		Computer computer = new Computer();
		
		buyer.buy(tv);
		System.out.println("현재 남은 돈은 : " + buyer.money + " 만원 입니다.");
		System.out.println("현재 보너스 점수는 : " + buyer.bonusPoint + " 점 입니다.");
		
		System.out.println();
		
		buyer.buy(computer);
		System.out.println("현재 남은 돈은 : " + buyer.money + " 만원 입니다.");
		System.out.println("현재 보너스 점수는 : " + buyer.bonusPoint + " 점 입니다.");
	} // main
} // PolyArgumentTest


'Java > Java SE' 카테고리의 다른 글

Java 인터페이스(interface)  (2) 2013.08.07
Java 추상클래스(abstract class)  (0) 2013.08.07
Java 제어자(modifier), 접근 제어자(access modifier)  (0) 2013.08.06
Java super, super()  (0) 2013.08.06
Java 오버라이딩(overriding)  (0) 2013.08.05

+ Recent posts