■ 서론
다형성을 구현의 다양함 정도로 설명했고 그 예시로 오버라이딩, 오버로딩을 들었다.
다형성에 대해 좀 더 알아보고자 이렇게 정리한다.
■ 바인딩
보통은 참조변수의 타입과 객체의 타입이 일치하지만, 변수의 타입과 객체의 타입이 다른경우를 볼 수 있다.
예를들면 Map mapping = new HashMap(); 이 있다.
어떤 시점에서, 메소드가 호출될 때 어떤 코드를 수행할 것인지가 결정된다.
이러한 결정을 메소드 호출을 메소드 정의에 바인딩(binding)한다고 한다.
많은 경우에, 메소드 정의에 대한 메소드 호출의 바인딩이 컴파일 시간에 일어날 수 있다.
그러나 다형 참조의 경우에는 실행 시간까지 바인딩을 할 수 없다.
정적바인딩(static binding / early binding) | 동적바인딩(dynamic binding / late binding) |
private, final, static 이 이에 해당한다. 컴파일러에 의해 컴파일시간에 결정된다. | 컴파일러는 객체의 타입을 알 수 없으므로, Dog타입으로 먼저 컴파일을 진행한 후, 실행 중 Pudle타입의 메소드가 호출된다. 런타임 중(실행시간)에 결정된다. |
class Dog { void sound(){ System.out.println("멍멍~~"); } } public static void main(String[] args) { Dog d = new Dog(); d.sound(); } | class Pudle extends Dog { void sound(){ System.out.println("푸들~~"); } } public class Test { Dog d = new Pudle(); d.sound(); } |
컴파일 시간에 많은 정보가 결정되므로 실행 효율이 높다. | 런타임 중에 자유롭게 결정되므로 유연하다. |
■ 상속에 의한 다형성
Animal creature = new Horse(); 라고 선언하면, 변수 creature는 Animal의 어떤 객체라도 참조할 수 있다.
또한 Animal을 상속받는 어느 클래스의 객체 Horse(예시)도 참조할 수 있다.
클래스의 계층구조의 최상단에는 Object가 있는데, Object는 모든 클래스의 객체를 가르킬 수 있다는 말이된다.
Animal을 상속받은 Horse, Hippo 클래스가 있다고 하자.
Animal creature;
creature = new Horse();
creature.move(); ㅡ 1번
creature = new Hippo();
creature.move(); ㅡ 2번
이때, creature의 타입은 Animal이지만,
1번에서는 Horse의 move()가, 2번에서는 Hippo의 move()가 실행된다.
이렇게 상속에 따른 다형의 객체를 참조할 수 있으며,
메소드 호출 또한 실행 당시의 참조 객체의 메소드를 선택하여 호출하는 것을 상속에 의한 다형성이라고 한다.
■ 인터페이스에 의한 다형성
인터페이스 역시 클래스와 마찬가지로 변수 타입으로 사용될 수 있다.
public interface Speaker{ public void speak(); public void announce(String str); } Speaker current; |
public class Philosopher implements Speaker{ System.out.println("Hello"); } System.out.println(str); } public void Listen(){ System.out.println("I got it"); }
|
라는 인터페이스와, 참조변수 current를 가정해보자.
참조변수 current는 Speaker 인터페이스를 구현하는 어떤 클래스의 객체라도 참조할 수 있다.
Philosopher 클래스가 Speaker를 implements 한다면
current = new Pilosopher(); 라고 바인딩 할 수 있다.
여기서 주의할 점은,
인터페이스 참조 변수를 사용하고 있을 때, 그 참조 변수가 가리키고 있는 객체가
인터페이스에 없는 다른 메소드를 포함하고 있다고 할지라도, 그 인터페이스에 정의되어 있는 메소드만을 호출할 수 있다.
current는 Philosopher 타입의 객체를 바인딩 했지만 Speaker 타입이기 때문에,
Listen()은 사용할 수 없고, Speaker 인터페이스가 가진 speak(), announce() 메소드를 사용할 수 있다.
특별한 상황에서 Listen() 메소드를 호출이 필요할 경우, 캐스팅을 사용해서 할 수도 있다.
Speaker special = new Philosopher();
((Philosopher)special).Listen();
■ 추천 사이트
예시가 아주 잘 나와있다.
https://opentutorials.org/module/516/6127
■ 출처
http://secretroute.tistory.com/entry/140819
http://blog.daum.net/_blog/BlogTypeView.do?blogid=0LoOX&articleno=6036856&_bloghome_menu=recenttext
http://hyeonstorage.tistory.com/266
'코딩 > Java 프로그래밍' 카테고리의 다른 글
OOP 용어 정리 (0) | 2016.12.14 |
---|---|
자바 Collections 클래스 Comparator (0) | 2016.11.26 |
[JAVA] Scanner nextInt()나 next() 사용 후 nextLine 입력 (0) | 2016.11.26 |
자바의 4대 특성 (2) | 2016.10.17 |