다형성(polymorphism)

김근호·2023년 5월 26일
0

Java

목록 보기
10/10

다형성(polymorphism)

다형성(polymorphism)이란 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미합니다.

자바에서는 이러한 다형성을 부모 클래스 타입의 참조 변수로 자식 클래스 타입의 인스턴스를 참조할 수 있도록 하여 구현하고 있습니다.

다형성은 상속, 추상화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 특징 중 하나입니다.

class Tv {
	boolean power;
    int channel;
    
    void power()       {  power = !power; }
	void channelUp()   { ++channel; }
    void channelDown() { --channel; }
}

class SmartTv extends Tv {
	Strung text;
    void caption() {  /* 내용생략 */}
}

지금까지 우리는 아래처럼 생성된 인스턴스를 다루기 위해서 인스턴스의 타입과 일치하는 타입의 참조변수만을 사용했다.

Tv t = new Tv();
SmartTv s = new SmartTv();

이처럼 인스턴스의 타입과 참조변수의 타입이 일치하는 것이 보통이지만, Tv와 SmartTv클래스처럼
서로 상속관계에 있을 경우, 다음과 같이 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있다.

Tv t = new SmartTv();

인스턴스를 같은 타입의 참조변수로 참조하는 것과 조상타입의 참조변수로 참조하는 것은 어떤 차이가 있을까?

SmartTv s = new SmartTv();
Tv      t = new SmartTv();

위의 그림처럼 조상타입의 참조변수보다 자손타입의 참조변수를 사용 할때가 인스턴스멤버가 더 많다.

둘 다 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용 할 수 있는 멤버의 개수가 달라집니다.

반대로 아래와 같이 자손타입의 참조변수로 조상타입의 인스턴스를 참조하면 컴파일 에러가 발생합니다. 그 이유는 실제 인스턴스인 Tv의 멤버 개수보다 참조변수 s가 사용할 수 있는 멤버 개수가 더 많기 때문입니다.

SmartTv s = new Tv();

참조변수의 형변환

  • 서로 상속관계에 있는 타입간의 형변환만 가능하다.
  • 자손 타입에서 조상타입으로 형변환하는 경우, 형변환 생략가능하다.

❗ 조상의 조상으로도 형변환이 가능하다. 따라서 모든 참조변수는 모든 클래스의 조상인 Object클래스 타입으로 형변환이 가능하다.

class Car { }
class FireEngine extends Car { }
class Ambulance  extends Car { }

FireEngine f = new FireEngine();

Car c = (Car)f;                 --- (1)
Ambulance a = (Ambulance)f;     --- (2)
FireEngine f2 = (FireEngine)c;  --- (3)
    

instanceof 연산자

참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof 연산자를 사용합니다. 주로 조건문에 사용되며, instanceof의 왼쪽에는 참조변수를 오른쪽에는 타입(클래스명)이 피연산자로 위치합니다. 그리고 결과로 boolean값인 true와 false중의 하나를 반환합니다.

void doWork(Car c) {
	if (c instanceof FireEngine) {
    	FireEngine fe = (FireEngine)c;
        fe.water();
        ...
    }
} 

앞에서 언급했던것처럼 조상타입과 자손타입중에 어디를 참조하냐에 따라서 사용 할 수 있는 인스턴스 멤버가 달라진다. 그렇기때문에 형변환을 통해서 인스턴스 멤버를 사용 할 수 있으려면 형변환이 필요하고, 그걸 판별하기 위해서 instanceof 연산자를 사용한다.

매개변수의 다형성

참조변수의 다형적인 특징은 메서드의 매개변수에도 적용됩니다.

class Product {
	int price;
    int bonusPoint;
}

class Tv       extends Product { }

class Computer extends Product { }

class Buyer {
	int money = 1000;
    int bonusPoint = 0;
}

Buyer클래스에 물건을 구입하는 매서드를 만들고, Tv를 살 수 있도록 Tv타입으로 매개변수를 받았다.

void buy(Tv t) {
	money = money - t.price;
    
    bonusPoint = bonusPoint + t.bonusPoint; 
}

그런데, buy(Tv t)로는 Tv밖에 사지 못 한다.
Computer를 사려면 위와 같은 방식으로 buy(Computer c)메서드를 또 작성해야 한다.
이처럼 물품이 늘어날때마다 매번 새로운 메서드를 작성해야 한다.

하지만 앞에서 배운 다형성을 매개변수에 적용하면 buy(Product p)이처럼 조상타입으로 매개변수를 사용하면 형변환을 통해서 상속받은 자손타입으로 다 가능해진다.
또한, Product클래스에 price와 bonusPoint가 선언되어 있기 때문에 참조변수 p로 사용이 가능하다.

위의 경우처럼 같은 조상타입을 가지는 서로 다른 종류의 객체들을 배열로도 관리 할 수 있다.

Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
profile
앞만 보고 나아가자!

0개의 댓글