본문 바로가기

Programming/JAVA

java : 상속을 통해 리턴타입을 보다 유연하면서도 강제할 수 있어요! (다형성)

제목이 좀 이상하네요. 한국 토박 스물여덟해를 지냈음에도 한국말이 서툰것 같습니다 -_-;

상속을 이용하면 좋은 점은 여러가지가 있습니다. 그 중 한가지를 소개해드리겠습니다.
(저와 같은 초보를 대상으로 하니~ 고수분들께서는 피식 웃어주시며 격려해주세요 ㅎㅎ)

메소드의 4대 요소 중 하나인 리턴값 타입은 무척 중요합니다. 이 리턴이 무엇이 되느냐만으로도
어느 정도 그 메소드를 직접 열어보지 않고도 메소드네이밍과 리턴타입으로 메소드의 기능을 추측할 수 있지요.
(물론 내공이 쌓여야겠지요... 전 아직 헤롱헤롱~)

이 리턴 타입에 대해서 다형성을 이용한다는 것은 보다 클라이언트 코드에게 명확한 코드를 작성할 수 있게
신뢰를(?) 심어줄 수 있습니다.

그럼 소스를 볼까요~

이하는 abstract 클래스로

key value를 삽입하고
key 들을 얻어오고
특정 key에 대해 value 를 얻을 수 있는 메소드를 선언하고 있습니다.  
import java.util.Set;

public abstract class AbstractKeyValue< k, v > {
	public abstract AbstractKeyValue< k, v > setter(String key, String value);
	public abstract Set< k > getKeys();
	public abstract Object getValue(K key);
}

이하 클래스는 위의 abstract 클래스를 상속받는 클래스입니다.
부모 추상클래스인 AbstractKeyValue 의 setter 메소드 return type만 자기 자신의 클래스타입을
선언해놓았습니다.

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class SonKeyValue< k, v > extends AbstractKeyValue< k, v > {

	private Map< string, string > keyValue;
	
	public SonKeyValue(){
		keyValue = new LinkedHashMap< string, string >();
	}
	@Override
	public SonKeyValue< k, v > setter(String key, String value) {
		if(!this.keyValue.containsKey(key)){
			keyValue.put(key, value);
		}
		return this;
	}
	@SuppressWarnings("unchecked")
	@Override
	public Set< k > getKeys() {
		return (Set < k >) keyValue.keySet();
	}
	@Override
	public String getValue(K key) {
		return keyValue.get(key);
	}
}
이렇게 작성된 구상클래스의 setter를 사용하는 클라이언트 코드는
이 구상 클래스의 setter 메소드에 대해서 보다 정확히 뭐하는 코드인지 알 수 있습니다.
setter 메소드를  . 연산자를 이용해서 꾸준히 사용할 수 있다는 것도 알 수 있죠.
(사실;;; 리턴타입을 AbstractKeyValue 로 선언해도 기능은 무리없기는 합니다만....
 내공이 부족해서 괜찮은 예제가 머리에 팍팍 떠오르질 않네요 ㅠㅠ)

이하 소스는 위의 구상 클래스를 사용하는 클라이언트 코드입니다.
import java.util.Set;

public class TestMain {

	public static void main(String[] args) {
		SonKeyValue < string, string > son = new SonKeyValue< string, string >();
		
		son.setter("a", "AAA");
		son.setter("b", "BBB");
		son.setter("c", "CCC").setter("d", "DDD");
		
		Set keyList = son.getKeys();
		for (String string : keyList) {
			System.out.println("key : " + string + ", value : " + son.getValue(string));
		}
	}
}

코드를 보면 알 수 있듯이 setter 메소드에 대해서 리턴 타입이 void인 메소드를 사용하는 것처럼
사용할 수도 있고 그것이 아닌 것 처럼 사용할 수도 있습니다.
SonKeyValue의 setter 메소드에서 return type이 자기 자신이기때문에 클라이언트 코드에서는
대입연산자를 활용하여 반환객체를 대입연산자로 다시 활용할 필요가 없습니다.
(이 부분은 예전에 포스팅한 자료중에 java는 포인터라는 자료를 참조하시면 도움이 될 것 같습니다.
 제가 글 재주가 없다보니 양해부탁드려요 ㅠㅠ)

이렇게 보다 key value에 대해 pair한 클래스들을 사용하려면 hashcode와 equals 메소드를
오버라이딩해서 사용해야함이 맞지만.... 우선 급하게 예제 코드를 작성하다보니 무시하였습니다~

이 포스팅에서 중요한 것은 리턴타입에 대해 다형성을 줄 수 있다는 것이죠^^;;
그것이 abstract method라 할지라도 말입니다~



※ 예제코드를 작성중에 유형매개변수(?)를 좀 사용하였는데요... 
조금 더 이 유형매개변수에 대해서 정확히 이해하게되고 여유가 있을 때 관련해서 포스팅해보도록 하겠습니다.