선생님, 개발을 잘하고 싶어요.

[오브젝트] 챕터 12 - 다형성 본문

일상/책 리뷰

[오브젝트] 챕터 12 - 다형성

알고싶은 승민 2022. 3. 23. 00:00

다형성을 달성하게 만든 동적 바인딩에 대해서 탈탈 턴 챕터입니다.

클라이언트가 보낸 메시지가 실제로 런타임에 어떻게 구체 클래스의 메서드를 실행하게 되는지 상속의 관점에서 잘 설명돼있습니다.

여기서 더 나아가서 상속은 이러한 동적 바인딩을 위한 경로 정의에 방법일 뿐이라는 이야기와 함께 경로 정의를 컴파일 타임 상속으로 처리한 게 아니라 런타임 객체간 체이닝으로 처리한 자바스크립트의 prototype의 예시를 들어주는 데 엄청 신기했습니다.

그런 식으로 실제 실행 시점 메서드를 결정한다는 메커니즘에서 합성이 어떻게 상속의 대체가 되는지 설명하는 부분까지 완벽했다고 생각합니다.


  • 도입</aside>
    • 상속 이외에도 다형성을 구현할 수 있는 방법은 많다.
    • 다형성은 런타임에 메시지를 처리하기에 적합한 메서드를 동적으로 탐색하는 과정에서 얻어진다.
  • <aside> 💡 상속의 목적은 코드의 재활용이 아니라 타입 계층 구조화다.
  • 다형성
    • 여러 타입을 대상으로 동작할 수 있는 코드를 작성할 수 있는 방법
    • 주로 서브타입 다형성에서 얘기할 예정
      • 메시지가 동일하더라도 수신한 객체의 타입에 따라 실제 수행되는 행동이 달라지는 능력
    <aside> 💡 상속의 진정한 목적은 다형성을 위한 서브타입 계층을 구축하는 것이다.<aside> 💡 런타임에 상속 계층 안에서 적절한 메서드를 선택하는 방법을 이해하는 게 목표
  • </aside>
  • </aside>
  • 상속의 양면성
    • 데이터 관점 상속: 부모에 정의한 모든 데이터를 자식 클래스 인스턴스에 자동 포함
    • 행동 관점 상속: 부모의 일부 메서드를 자식에 포함
    • 상속 메커니즘 이해를 위한 개념들
      • 업캐스팅
      • 동적 메서드 탐색
      • 동적 바인딩
      • self 참조
      • super 참조
    • 데이터 관점 상속
      • 개념적으로 자식 클래스 인스턴스 안에 부모 클래스 인스턴스가 포함되는 것
    • 행동 관점 상속
      • 부모에 정의한 일부 메서드를 자식 메서드로 포함시키는 것
      • 메서드는 동일한 클래스 인스턴스 끼리 공유
      • 클래스 로드 한번 하고 인스턴스 별로 클래스를 가리키는 포인터를 가지게됨
  • 업캐스팅과 동적 바인딩
    • 같은 메시지, 다른 메서드
      • 업캐스팅: 부모 타입으로 선언된 변수에 자식 타입 인스턴스 할당이 가능
      • 동적 바인딩: 메시지를 수신하는 객체에 따라 실행되는 메서드가 결정, 적절한 메서드를 실행 시점에 결정
      • 부모 타입에 메시지를 전송해도 실행 시에는 실제 클래스 기반으로 실행될 메서드가 선택된다.
    • 동적 바인딩
      • 함수 호출과 메시지 전송의 차이
      • 함수 호출 → 컴파일타임 결정
      • 메시지 전송 → 런타임 결정 → 동적 바인딩
  • 동적 메서드 탐색과 다형성
    • class, self, parent 포인터
    • 메서드 탐색은 자식 → 부모 방향으로 진행
    • 자동적인 메시지 위임
    • 자식이 이해할 수 없는 메시지는 부모에 처리를 위임
    • 실제로 어떤 메서드를 실행할지는 실행 시점에 self 참조를 이용해서 결정한다.
    • 자동적인 메시지 위임
      • 상속 계층을 정의 == 이해할 수 없는 메시지 처리를 위임할 객체로의 물리적 경로를 정의하는 것
      • 상속 계층 정의 == 메서드 탐색 경로 정의
    • 동적인 문맥
      • 자기 자신에게 메시지를 전송하는 self 전송이 코드 상 직관과 위배될 수 있다.
      • self는 런타임에 결정된다.
    • 이해할 수 없는 메시지
      • 정적 타입 언어는 컴파일 에러를 발생
      • 동적 타입 언어는 별도의 메시지 발생
        • 해당 메시지에 대한 기본 처리로 예외 던지기 설정
        • 별도의 처리를 구성하는 게 가능...!
    • self vs super
      • super: 지금 이 클래스의 부모 클래스 부터 메서드 탐색을 시작하세요~
        • 컴파일 타임에 정적으로 결정된다. (물론, Mixin과 같은 메커니즘에서는 ? 동적이지)
  • 상속 대 위임
    • 상속을 바라보는 다른 시각
      • “자식에서 부모로 self 참조를 전달하는 메커니즘”이 상속이다.
    • 자신이 수신한 메시지를 다른 객체에게 동일하게 전달해서 처리를 요청하는 것을 위임이라고 한다.
      • 자신이 정의하지 않거나 처리할 수 없는 속성, 메서드 탐색 과정을 다른 객체로 이동
      • 위임의 정확한 용도는
        • 클래스를 이용한 상속 관계를 객체 사이의 합성 관계로 대체해서 다형성을 구현하는 방법
    • 위임 → 객체 사이의 동적인 연결 관계를 이용해 상속을 구현하는 방법
    • 프로토타입 기반의 객체지향 언어
      1. 메시지를 수신한 객체의 prototype안에서 메시지에 응답할 적절한 메서드를 검사
      2. 존재하지 않는다면, Prototype이 가리키는 객체를 따라 메시지 처리 위임
      • prototype 체인으로 연결된 객체 사이에 메시지를 위임하여 상속을 구현한다.
        • 메시지 위임 방법 차이!
      • 클래스 없이도 객체 사이의 협력 관계 구축 가능
      • 상속 없이도 다형성 구현 가능

<aside> 💡 클래스 기반 상속 & 객체 기반 위임 사이에 같은 기본 개념과 메커니즘이 공유된다.

</aside>

  • 같은 기본 개념, 메커니즘
    • 메시지 처리를 위임하기 위한 경로를 정의한다.
    • 경로의 시작점은 런타임에 self이다.
    • 경로 상 자식이 처리할 수 없는 메시지는 부모에게 위임한다.
    • 경로를 정의하는 방법: 상속, Prototype 체이닝
Comments