class Tv {
boolean power;
int channel;
void power() {
power = !power
}
void channelUp() {
channel++;
}
void channelDown() {
channel--;
}
}
class SmartTv extends Tv {
String text;
void cation() {}
}
생성된 인스턴스를 아래와 같이 2개 생성했을 때 어떤 차이점이 있을까?
// 둘의 차이 알아보기
SmartTv s = new SmartTv();
Tv t = new SmartTv();
조상 타입은 참조변수로 자손타입의 인스턴스를 참조할 수 있다.
반대로 자손타입은 참조변수로 조상타입의 인스턴스를 참조할 수 없다.
서로 상속관계에 있는 클래스 사이에서만 가능하기 때문에 자손 타입의 참조변수를 조상 타입의 참조변수로, 조상 타입의 참조변수를 자손 타입의 참조변수로의 형 변환만 가능하다.
자손 타입 -> 조상 타입 (Up-casting): 형 변환 생략 가능
자손 타입 <- 조상 타입 (Down-casting): 형 변환 생략 불가
class Car {
String color;
int door;
void drive() {}
void stop() {}
}
class FireEngine extends Car { // 소방차
void water() {}
}
class Ambulance extends Car { // 엠뷸런스
void siren() {}
}
[형 변환 예시]
Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
car = fe; // car (Car)fe; 에서 형 변환 생략됨. 업 캐스팅
fe2 = (FireEngine) car; // 형 변환 생략 불가. 다운 캐스팅
참조변수가 가리키는 인스턴스의 자손타입으로 형 변환은 허용되지 않는다. 그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요하다.
참조변수가 참조하고 있는 인스턴스의 실제 타입을 아아보기 위해 instanceof 연산자를 사용한다.
public static void main(String args[]) {
FireEngine fe = new FireEngine();
if (fe intanceof FireEngine) {
System.out.println("This is a FireEngine instance.");
}
if (fe intanceof Car) {
System.out.println("This is a Car instance.");
}
if (fe intanceof Object) {
System.out.println("This is an Object instance.");
}
System.out.println(fe.getClass().getName()); // 클래스 이름 출력
}
위의 실행 결과
This is a FireEngine instance.
This is a Car instance.
This is an Object instance.
FireEngine
=> 어떤 타입에 대한 instanceof 연산의 결과가 true라면 검사한 타입으로 형 변환이 가능하다.
참조변수의 다형적인 특징은 메서드의 매개변수에도 적용된다.
class Product {
int price;
}
class Tv extends Product {}
class Computer extends Product {}
class Buyer {
int money = 1000;
}
구매자가 컴퓨터 또는 TV를 구매할 때 메서드의 매개변수에 다형성을 적용하여 메서드를 간단히 처리할 수 있다.
[다형성 적용하지 않았을 때]
void buy(Computer c) {
money = money - c.price
}
void buy(Tv t) {
money = money - t.price
}
[다형성 적용]
void buy(Product p) {
money = money - p.price
}