[객체 지향 프로그래밍] 다형성 (Polymorphism)

sy·2023년 7월 2일
0

다형성 (Polymorphism)

  • 여러가지 형태를 가질 수 있는 능력
  • 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 프로그램적으로 구현하였다.
  • 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다.
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();
  • 참조 변수 t는 CationTv 인스턴스의 모든 멤버를 사용할 수 없다.
  • 둘 다 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.

조상 타입은 참조변수로 자손타입의 인스턴스를 참조할 수 있다.
반대로 자손타입은 참조변수로 조상타입의 인스턴스를 참조할 수 없다.

참조변수의 형 변환

서로 상속관계에 있는 클래스 사이에서만 가능하기 때문에 자손 타입의 참조변수를 조상 타입의 참조변수로, 조상 타입의 참조변수를 자손 타입의 참조변수로의 형 변환만 가능하다.

자손 타입 -> 조상 타입 (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 연산자

참조변수가 참조하고 있는 인스턴스의 실제 타입을 아아보기 위해 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
}

0개의 댓글