Notice
Recent Posts
Recent Comments
Link
Tags
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

JongDDA의 한걸음 한걸음씩

[Java] 다형성(Polymorphism) 본문

개발/Java

[Java] 다형성(Polymorphism)

종따 2021. 8. 17. 21:51
728x90

다형성(Polymorphism)

다형성이란 '여러 가지 형태를 가질 수 있는 능력'을 의미하며, 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 프로그램적으로 구현하였다. 이는 부모클래스 타입의 참조변수로 자식클래스의 인스턴스를 참조할 수 있도록 하였다는 말이다.

 

다형성이란?

  1.  여러가지 형태를 가질 수 있는 것
  2.  하나의 메소드나 클래스가 있을 때 이것들이 다양한 방법을 동작하는 것, 대표적으로 오버로딩, 오버라이딩이 있다.
  3.  하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것

 

참조변수의 형변환

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

 

// 부모클래스 Car 클래스를 자식클래스인 FireEngine 과 Ambulance 클래스가 상속받고 있다.
class Car { } 
class FireEngine extends Car { }
class Ambulance extends Car { }

FireEngine f = new FireEngine();

Car c = (Car)f;	// 조상인 Car타입으로 형변환 (생략가능)
FireEngine f2 = (FireEngine)c;  // 자손인 FireEngine타입으로 형변환(생략불가)
Amblulance a = (Ambulance)f;  // 애러, 상속관계가 아닌 클래스 간의 형변환 불가

 

기본형의 형변환과 달리 참조형의 형변환은 변수에 저장된 값(주소값)이 변환되는 것이 아니다.

 

Car c = (Car)f;       // f의 값(객체의 주소)을 c에 저장, 
				// 타입을 일치시키기 위해 형변환 필요(생략가능)
f = (FireEngine) c; 	// 조상타입을 자손타입으로 형변환하는 경우 생략불가

 

서로 상속관계가 있는 타입간의 형변환은 양방향으로 자유롭게 수행될 수 있으나, 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다. 그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 먼저 확인하는 것이 중요하다.

 

instanceof 연산자

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

instanceof를 이용한 연산결과로 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.

 

void doWork(Car c) {
			if(c instanceof Ambulance) {		// 형변환이 가능한지 확인
				Ambulance am = (Ambulance) c;	// 가능하다면 형변환
				am.move();
			}
		}

위의 코드는 Car타입의 참조변수 c를 매개변수로 하는 메서드이다. 이 메서드가 호출될 때, 매개변수로 Car클래스 또는 그 자손 클래스의 인스턴스를 넘겨받겠지만 매서드 내에서도 정확히 어떤 인스턴스인지 알 길이 없다. 그래서 instanceof 연산자로 참조변수 c가 가리키고 있는 인스턴스의 타입을 체크하고, 적절히 형변환한 다음에 작업을 해야한다. 

 

매개변수의 다형성

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

class Product{
	int price;		
    int bonusPoint; 
}
class Tv extends Product {}
class Computer extends Product {}

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

위 코드는 자식클래스 Tv 와 Computer 가 부모 클래스 Product를 상속받은 것이다. 여기에 Buyer 클래스에 물건을 구입하는 기능의 메서드를 추가해보자

 

void buy(Tv t){
	// 돈 계산 
	money = money - t.price;
    // 보너스 포인트 계산
    bonusPoint = bonusPoint + t.bonusPoint;
}
void buy(Computer c){
	money = money - c.price;
    bonusPoint = bonusPoint + c.bonusPoint;
}

위 코드는 Tv와 Computer를 구매할 수 있도록 각각의 매개변수를 가진 메서드로 표현하였다. 이렇게 되면 제품이 늘어나면 늘어날수록 메서드를 추가해줘야 하고 코드가 계속 늘어날 것이다. 그러나 메서드의 매개변수에 다형성을 적용하면 이 문제를 해결할 수 있다.

 

void buy(Product p){
	money -= p.price;
    bonusPoint += p.bonusPoint;
}

매개변수가 Prodect타입의 참조변수라는 것은, 메서드의 매개변수로 Product클래스의 자식 타입의 참조변수면 어느 것이나 매개변수로 받아들일 수 있다는 뜻이다. 따라서 이 방법으로 제품이 얼마나 추가가 되든 제품이 Product 클래스를 상속받기만 하면 buy메서드의 매개변수로 받아들여질 수 있다.

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형

'개발 > Java' 카테고리의 다른 글

[Java] 인터페이스(Interface)  (0) 2021.08.18
[Java] 추상 클래스(abstract class)  (0) 2021.08.18
[Java] 제어자(modifier)  (0) 2021.08.17
[Java] 상속(Inheritance)  (0) 2021.08.16
[Java] 생성자(Constructor)  (0) 2021.08.15
Comments