상세 컨텐츠

본문 제목

자바공부<4> - 다형성

JAVA

by oimb 2018. 7. 9. 17:59

본문


1. 다형성


오늘은 다형성에 대해 알아보자


다형성에 대해 설명 하기전에 상속에 대하여 간단하게 살펴 보면


1. 재사용성 증가

2. 중복성이 감소 되어 간결성이 증가

3. 이로인해 시간이 절약


이러한 상속의 장점들이 있다.


자 그럼 다형성이란 무엇 일까? 인터넷 검색 결과  '여러 가지 형태를 가질 수 있는 능력'  이라고 한다.

이를 우리 자바식으로 적용 시킨다면 부모 클래스타입의 참조 변수로 자식 클래스의 인스턴스를 참조할 수 있도록 한다. 라고 생각 하면 되겠다.




출처 : 자바의 정석



자 이 그림을 보자  ,  왼쪽은 상속 관계를  보여주고  오른쪽은 이 상속 관계로 인해 만들어진 영역을 보여준다. 

다형성에서 초점을 맞춰야할 곳은 오른쪽이다.


Tv t = new Tv();

CationTv c =new CaptionTv(); 


이러한 코드가


Tv t = new CaptionTv(); 


로 사용할 수 있다는 것이다.  왜?  상속 관계니까 ? !   반은 맞다. 아니 그냥 맞다 근데 이해를 좀더 쉽게 하기 위해서 설명을 더하자면 

한 참조 변수에 인스턴스를 넣을 때 고려 해야 될 점은 상속 관계 이면서 '참조변수가 해당 인스턴스의 멤버를 전부 참조할 수 있는가? 이다.'

위의 그램을 보면 Tv의 멤버가 CaptionTv 의 멤버의 수보다 적다. 이는 상속관계에 있어 당연히 부모 클래스는 자식 클래스의 멤버 개수와 같거나 적을 수 밖에 없다. 이 때문에 위의 코드는 성립한다

그럼 반대로


CatptionTv c = (CaptionTv) new Tv();   는 ?  이는 참조변수(c)가 참조하려는 멤버 개수가 인스턴스(new Tv())의 멤버 개수 보다 많으므로 불가능하다.




2. 형변환


기본형 변수의 형변환을 먼저 알고 있어야 한다. 

기본형 변수에서 

큰타입 -> 작은타입 (다운 캐스팅)

작은타입 -> 큰타입  (업 캐스팅)

두 과정에서 형변환의 생략 유무가 정해진다. 업캐스팅의 경우는 생략가능 하지만 다운 캐스팅의 경우 명시해줘야 한다.

객체에 있어서도 이와 비슷하다.  다만 객체의 관계가 상속 관게여만 한다는 점이 있다



이런 상속 관게를 가지고 있는 종족? 이 있다

여기서 


테란 ter = null;

마린 m = new 마린();

마린 m2 = null;


탱크 t = new 탱크();

탱크 t2 = null;


1. ter = m;    // 업캐스팅

2. m2 = (마린)ter;  // 다운 캐스팅 따라서 생략 불가능


1번 과 2번의 차이는 업캐스팅과 다운 캐스팅의 차이로 보면 되겠다

추가로 다운캐스팅시 명시적으로 형변환 해줘야하는 이유를 덧붙이자면 문제 발생의 가능성이 생기기 떄문인데  , 이를 위해서 형변환을 수행하기전에 instanceof를 통해 형변환의 가능 유무를 판별하는 것이 좋다.


형변환은 참조 변수의 타입만 변환 하는 것이지 그 참조변수가 참조하는 인스턴스를 변환하는 것은 아니다. 따라서 형변환을 통해서는 참조변수가 참조할 수 있는 멤버의 개수만을 조절하는것 이다. 

즉 , ter = m 인 상태에서  t2 = (탱크)ter; 은 불가능 하다. 

참조 변수만 본다면 부모 클래스에서 자식클래스로 다운캐스팅 하는것으로 명시적으로 형변환도 명시 했지만  참조 변수가 참조하고 있는 인스턴스는 변하지 않으므로( ter는 마린 객체를 담고있음)  에러가 발생한다.


이러한 형변환을 방지 하기 위해서  instanceof 를 사용하는데 

 

(참조변수)  instanceof  (피연산자)

형식이며 검사한 타입으로 형변환이 가능하면 true 불가능하면 false를 반환한다.


1. 참조 변수가 가리키는 인스턴스가 피연산자와 동일한 타입이면 당연히 형변환 가능하고 

2. 참조 변수가 가리키는 인스턴스가 피연산자보다 상위 클래스 이면 이는 다운 캐스팅해야 되므로 불가능하고

3. 참조 변수가 가리키는 인스턴스가 피연산자보다 하위 클래스 이면 이는 업  캐스팅 하는 것이므로 가능하다.


즉 

if (  x  instanceof 마린)

마린  m = (마린)x ;

else if ( x instanceof 탱크 ) 

탱크 t = (탱크)x; 


이렇게 참조변수 x 가 가리키는 인스턴스에 초점을 맞춰 형변환 가능유무를 판정 하는 것이다.


정리 하자면 

앞서 말한 '참조변수가 해당 인스턴스의 멤버를 전부 참조할 수 있는가? 는 참조 변수의 형변환에 초점을 맞춘 개념이라면

인스턴스의 기준에 맞춰 다시 설명 하자면 '상속관계에 있는 타입간(참조 변수) 형변환은 자유롭게 수행될 수 있으나 여기서 참조변수가 가리키는 인스턴스의 자식타입으로의 형변환은 허용 되지 않는다'  로 설명할 수 있겠다


다형성에 대해서 최대한 쉽게 설명하려고 했는데..그래도 어려운것 같다.. 이 부분이 그만큼 어렵고 중요한 부분이다 보니 요약하기 힘들었다.

관련글 더보기