상속과 다형성을 이해하기 위해서는, static binding과 dynamic binding에 대해서 이해하는 것이 핵심이라고 생각합니다. 오늘 이에 대해서 간단하게 알아보겠습니다.

 

 


 예제 프로그램 1을 보겠습니다.

 

 Obj class가 있고, Obj를 상속받은 MyObj가 있습니다. 이 2개는 static 메소드인 foo를 가지고 있습니다.

 

 

 Main 클래스는 위와 같습니다. 이 때, 실행 결과는 어떻게 나올까요?

 

 

 Obj, Obj, MyObj가 나옵니다. o1, o2가 Obj를 참조하는 변수이기 때문입니다. 이러한 정보는 complie 타임에 올라갑니다.

 

 

Obj의 필드 x 값이 100입니다. 그리고 MyObj의 필드 x 값이 0입니다.

 

 

 Main 클래스는 위와 같습니다. 실행 결과가 어떻게 나올까요?

 

 

 100, 100, 0이 나옵니다. o1과 o2는 Obj를 참조하는 변수이고, mo는 MyObj를 참조하는 변수이기 때문입니다. Type 정보만을 읽어서, 컴파일 타임에 bound 시켰다는 의미입니다.

 

 


 문제는, 동적 바인딩입니다. 프로그램 2를 보겠습니다.

 

 함수 앞에 static, final, private가 붙지 않았습니다. 그리고 Obj에도 foo라는 메서드가 있고, Obj를 상속받은 MyObj에도 foo가 있습니다.

 

 Main 함수는 위와 같습니다. 실행 결과는 어떻게 나올까요?

 

 

 o1.foo()라던지, mo.foo()는 실행 결과를 이해하기 쉽습니다. 그런데, o2.foo()를 호출하면 왜 MyObj가 출력될까요? 일단, MyObj와 Obj에 foo라는 메서드가 있는 것은 맞습니다. 그러면, o2.foo()가 어느 클래스에 있는 foo를 실행할지에 대해서는 언제 선택할까요? 이는, 실행 시간에 결정을 합니다.

 

 

 23번째 줄을 수행한 후에 메모리 상황을 그려보면 위와 같습니다. o2가 Obj를 참조하는 변수이지만, 실제로는 MyObj 객체를 참조하고 있습니다. 중요한 것은 이 부분입니다. 그렇기 때문에. override가 된 foo로 들어갑니다.

 

 

 MyObj의 foo는 MyObj를 출력합니다. 따라서, o2.foo()를 호출하면, MyObj가 출력됩니다. 부모 참조변수에 자식 객체의 참조를 집어넣었는데요. 이를 upcasting이라고 합니다.

 

 


 프로그램 3을 보겠습니다.

 

 

 MyObj에는 foo2 메서드가 있습니다.

 

 

 o2.foo2()에 빨간색 줄이 그어져 있습니다. 이는 Obj에 foo2가 정의되어 있지 않기 때문입니다.