by

부모 클래스에서, 자식 클래스의 메서드를 다이나믹 호출하기

파이썬으로 작성된 인터프리터를 C#으로 옮겨 짜다가 졸라 신기한 코드봤다.
간결하게 쓰자면 대강 이런 코드였음.

def visit_node(self, node):
    targetType = getType(node)
    callTarget = visit_ + str(targetType)
    visitor = getattrib(self,calltarget)
    return visitor(node)

심지어 클래스에 다른 메서드도 없음. 30분 고민후 아하! 하고 의도로 파악했다.

미래에 구현될 자식 클래스의 메서드 이름을 미리 예상해서, 다이나믹으로 호출하는 코드구나!

즉, 부모가 '명단에도 없는' 자식 클래스의 메서드를 다이나믹하게 호출하는 코드였다.
강타입 언어만 쓰니까 약타입에서 가능한 맥락을 이해 못했던 것이다.

node_visitor 클래스를 상속한 인터프리터 클래스에, visit_num, visit_operator 등의 메서드가 존재해서 알 수 있었다.

getattrib은 첫번째 입력으로 오브젝트 A, 두번째 입력으로 해당 오브젝트에서 가져오고 싶은 프로퍼티(변수나 메서드) B의 이름을 넣어주면, 오브젝트 A로 부터 B를 꺼내와주는 파이썬 빌트인 메서드다.

나는 getattrib에 자기자신을 집어넣는게 이해가 안됬던 것이다.
왜냐면 node_visitor 클래스에는 visit_node 이외의 다른 메서드는 존재하지도 않고, 자신의 스코프에 있는 모든 메서드와 필드는 self.~ 로 접근 가능하니 저럴 필요가 없거든.

  • 그런데 node_visitor를 상속한 자식 클래스에서 visit_int()라는 메서드를 구현했다고 했다고 하자.

visit(999) 라고 메서드를 호출하면, 999의 타입은 int이며, callTarget에는 visit_int라는 문자열이 할당된다.

그리고 visitor = getattrib(self, visit_int) 를 통해 visitor 라는 이름으로 visit_int() 메서드를 가져올 수 있게된다. 그리고 return visitor(node)를 통해 결론적으로 return visit_int(999)을 실행하는 꼴이됨.

꽤 재밌는 코드였지만, C#에서는 같은 방식으로 구현하기 힘들기 때문에 dynamic 키워드를 적절히 섞어서 추상 클래스로 위 구조를 비슷하게 구현했다는 이야기.

끝~