일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- heroku
- JAVA11
- SpringBoot 2
- Kadane's Algorithm
- R
- array
- Easy
- 자바 스레드 실행 순서 제어
- 자바 thread 실행 순서 제어
- 수학
- 사칙연산
- 카데인 알고리즘
- 자바입력
- scanner
- hash table
- input
- Today
- Total
DeFacto-Standard IT
[JAVA] Static Method Dispatch, Dynamic Method Dispatch, Double Dispatch 본문
[JAVA] Static Method Dispatch, Dynamic Method Dispatch, Double Dispatch
defacto standard 2018. 5. 1. 16:56Method Dispatch : 어떤 메소드를 호출할지 결정하여 실제로 실행시키는 과정을 말한다.
1) Static Dispatch
컴파일 시점에서, 컴파일러가 특정 메소드를 호출할 것이라는 걸 명확하게 알고있는 경우이다.
컴파일 시 생성된 바이트 코드에도 이 정보가 그대로 남아있다.
런타임(실행 시점)이 되지 않아도 미리 결정하는 개념이다.
함수를 오버로딩하여 사용하는 경우, 인자의 타입이나 리턴타입 등에 따라 어떤 메서드가 호출될 지 명확하기 때문에,
경우 역시 '미리 알 수 있다' 고 할 수 있다.
이 두개의 오버로딩 된 메서드는 전혀 다른 메서드로 구분되기 때문이다.
상위 개념인 Super 클래스가 존재하더라도,
Sub sub = new Sub() 와 같이 서브 클래스를 레퍼런스로 선언하고 서브 클래스의 인스턴스를 만든다면 이 역시도 Static Dispatch에 해당한다.
2) Dynamic Dispatch
상위 개념인 Interface 혹은 Abstract Class에서 정의된 abstract method를 호출하는 경우에 해당한다. 인터페이스로 가정하겠다.
하위 클래스에서는 상위 인터페이스에서 정의된 메서드를 반드시 Overriding 하여 구현해야 한다.
Static Dispatch에서
Sub sub = new Sub();를
Super super = new Sub();로 변경한다면, 이것은 Dynamic Dispatch에 해당된다.
자바의 기본으로 돌아가서,
Super라는 인터페이스에서 a()라는 메서드가 정의되어있다고 가정하자.
이 Super인터페이스를 구현하는 Sub 클래스는 반드시 a()를 구현해야 한다.
또한, Sub 클래스는 자신만이 가지는 b(), c()등의 메서드를 추가적으로 구현할 수 있다.
위의 경우, 자바에서는 Super super = new Sub(); 와 같은 객체의 생성과 바인딩을 허락한다.
super객체는 Super라는 인터페이스타입이다. 따라서, b(), c()가 구현되어있는 Sub클래스를 할당할지라도,
super객체를 통해서는 a() 메서드밖에 접근할 수 없다. 즉, '현재 바인딩 되어있는 클래스가 무엇인지 모른다'고 할 수 있다.
물론, Super super = new Sub(); 에서 new Sub(); 라는 문장 때문에, 'Sub 클래스가 명확히 보인다'라고 반론할 수도 있다.
그렇다면, Super 의 레퍼런스를 받아서 동작시키는 경우는 어떻게 판별할 것인가?
예를 들어 Client에서는
main() {
Super super = new Sub();
new Dispatcher().doAction(super);
}
와 같이 구현했다고 생각해보자. 아래는 Disaptcher Class이다.
class Dispatcher {
public void doAction(Super super) {
super.doAction();
}
}
Client에서는 개발자가 new Sub()라는 문장을 보고
1. Super는 상위 클래스 내지 인터페이스이며
2. Sub는 Super를 상속 또는 구현하는 클래스
라는 사실을 도출할 수 있다.
하지만 이를 Dispatcher Class의 정의부분만 보고서는 판단할 수 없다.
어떤 SubClass가 바인딩 되든 상관 없이, Super라는 추상타입만을 받을 것이고, 어쨋든 a()가 구현되어 있을테니 실행 시킬 것이고, 현재 바인딩된 SubClass에서 구현한 메서드를 수행하는 것이다.
이 메서드의 호출은 Runtime시에 결정되고, Dynamic Dispatch에 해당한다.
* 메서드 호출 과정
1. receiver parameter
위 소스코드에서 super라는 object의 'this'라는 키워드로 쓰이는 요소가 파라미터로 자동으로 들어가게 된다. 이 파라미터를 receiver parameter라고 한다.
소스 상에서는 보이지 않으나, 자바 스펙에 기술되어있다.
Super super = new Sub();
super.a();
라고 한다면, a()호출 시 receiver parameter는 new Sub()에서 생성된 객체의 this가 해당된다
2. Method Reference를 통해 자식 클래스의 메서드를 실행시킨다.
3) Double Dispatch
Dispatch가 연속으로 이뤄지는 것을 말한다. 이를 사용하는 대표적인 Pattern은 Visitor Pattern이 있다.
Visitor Pattern에서는 Element와 Visitor라는 개념이 있다. 둘 다 추상적인 개념인 Element와 Visitor 인터페이스로서 정의된다.
Visitor v = new ConcreteVisitor();
Element e = new ConcreteElement();
e.accept(v);
를 수행한다고 가정해보자.
e는 추상타입인 Element의 레퍼런스로서, 인터페이스이므로 e.accept() 수행 시 Element를 구현하는 new ConcreteVisitor()의 인스턴스가 receiver parameter로 넘어가게 된다.
Dynamic Dispatch가 이루어지게 되어 ConcreteElement에 정의된 accept()가 수행될 것이다.
ConcreteElement에 정의된 accept()의 정의는 다음과 같다.
public void accept(Visitor v) {
// Double Dispatch
v.visitConcreteElement(this);
}
accept()에서는 다시 추상적인 객체인 Visitor를 인자로 받는다.
Visitor에 정의된, 각 ConcreteElementA/B/C 등에서 각각의 클래스가 필요한 로직을 수행시키도록 한다.
이 역시도 Dynamic Dispatch가 이루어지게 되어 ConcreteVisitor에 정의된 accept()내의 visitConcreteElement가 수행된다.
이때 인자로서 this를 넘기게 된다.
즉,
1. Element# accept(Visitor visitor) 실행
2. ConcreteElement# visitor.visitConcreteElement(this) 실행 // Dynamic Dispatch #1
3. ConcreteVisitor# visitConcreteElement(ConcreteElement ce) 실행 // Dynamic Dispatch #2
과 같은 순서를 가지게 된다.
* JPA&Hibernate 등을 사용할때, instanceof 연산을 사용하여 Polymorphic Query를 사용하는 경우, 추상 클래스 타입으로 읽어오므로, 서브 클래스의 정보를 가져올 수 없다. 이를 해결할 수 있는 방법은 없다.
하지만 Double Dispatch를 사용하는 Visitor Pattern을 사용한다면, 요소의 내부까지 들어가도록 제어할 수 있다. 내부로 들어가는 호출이 일어나는 순간, proxy(추상 클래스)를 실제 SubClass까지 확장가능하다.
실제로, Super super = new Sub();
수행 후 super.getClass().getSimpleName()을 출력해보면, 'Super'가 아닌 'Sub'라는 문자열이 찍힌다.
이러한 것을 Proxy Visitor Pattern이라고 한다.
Proxy Visitor Pattern은 추상 클래스를 활용하여 서브 클래스의 정보를 DB로부터 쿼리할 수 있는 ORM Pattern으로 분류된다.
JPA&Hibernate 프로그래머들은 반드시 알아둬야 한다.
'Java > References' 카테고리의 다른 글
jackson-databind Polymorphic Serialization / Deserialization (1) - 2-Depth (4) | 2019.03.10 |
---|---|
[JAVA] Method Signature, Method Type, Method Reference (0) | 2018.05.01 |
Java의 특징 (0) | 2017.11.15 |
Wrapper 클래스 (0) | 2017.11.15 |
Primitive Type / Reference Type (0) | 2017.11.15 |