본문 바로가기

CS/CS Book

[오브젝트] ch12 다형성

💡이 글은 조영호, 『오브젝트: 코드로 이해하는 객체지향 설계』, 위키북스(2019) 책을 읽고 작성한 글입니다.

 

저자는 다형성(polymorphism) 그리스어로 다양한을 의미하는 poly와 형태를 의미하는 morph의 합성어임을 12장 앞에서 설명해 주며 시작한다.

 

동물 클래스가 있을 때 소리 내는 행위가 있고 고양이 클래스에서는 야옹, 강아지 클래스에서는 왈왈이라 하였을 때 고양이의 소리 내는 소리 내는 것을 동물 클래스의 소리 내는 것으로 형태를 바꾸어 표현할 수 있다.

이렇게 소리 낸다는 행위는 같지만 누가 그 행위를 하였는가에 따라 다양하게 표현할 수 있게 된다.

다형성의 분류

다형성의 분류에는 매개변수 다형성, 포함 다형성, 오버로딩 다형성, 강제 다형성 4가지가 있음을 알려준다.

 

매개변수 다형성의 경우 제네릭 프로그래밍과 관련이 높고 “클래스의 인스턴스 변수나 메서드의 매개변수 타입을 임의의 타입으로 선언한 후 구체적인 타입으로 지정하는 방식”(p391)을 말한다.

 

강제 다형성의 경우 “언어가 지원하는 자동적인 타입 변환이나 사용자가 직접 구현한 타입변환을 이용해 동일한 연산자를 다양한 타입에 사용할 수 있는 방식”(p391)을 말한다. 자바 스크립트에서 “4” + 2라는 식의 숫자 2가 문자열 ”2”로 타입 변환이 되고 식의 결과가 문자열 “42”로 되는 것으로 볼 수 있다.

$> "4" + 2
'42'

오버로딩 다형성 “일반적으로 하나의 클래스 안에 동일한 이름의 메서드가 존재하는 경우”(p390)을 말한다.

 

포함 다형성 “메시지가 동일하더라도 수신한 객체의 타입에 따라 실제로 수행되는 행동이 달라지는 능력을 의미한다.”(p390) 포함 다형성의 경우 객체지향 프로그래밍에서 널리 알려진 형태의 다형성이다. 위 예시에서 동물의 소리 내는 행위가 다양한 모습으로 표현될 수 있던 것과 같다.

 

다형성의 개념

이번 장에서는 다형성을 설명하기 위해 업캐스팅, 동적 바인딩, 동적 메서드 탐색 등의 개념을 활용한다.

업캐스팅

업캐스팅의 경우 자식 클래스의 인스턴스를 부모 클래스의 타입으로 변환하는 것을 말한다.

Animal이 부모 클래스이고 Cat이 자식 클래스 일 때, Cat의 인스턴스를 부모클래스 타입인 Animal로 캐스팅하는 것이다.

Cat cat;
(Animal)cat;

반대의 개념으로 부모 클래스의 인스턴스를 자식 클래스 타입으로 변환하기 위한 명시적 타입 캐스팅으로 다운캐스팅이 있다.

Animal의 인스턴스를 자식 클래스 타입인 Cat으로 캐스팅하는 것이다.

Animal animal;
(Cat)animal;

동적 바인딩

바인딩이 동적으로 된다는 개념인데 동적의 의미는 런타임(runtime) 즉, 프로그램이 실행될 때를 의미한다. some.sound()라는 메서드가 있을 때 sound()가 어느 클래스의 메서드인지는 sound가 가리키는 객체가 실제로 어떤 클래스의 인스턴스인지, sound() 메서드가 해당 클래스의 상속 계층의 어디에 위치하는지를 알아야 한다.

반대 개념으로 정적 바인딩이 있으며 컴파일 타임에 호출할 함수를 결정하는 방식이다. 코드를 작성하는 시점에 호출될 코드가 결정된다.

동적 메서드 탐색

sound()라는 메서드가 어느 클래스의 인스턴스인지, 해당 클래스의 상속 계층 어디에 있는지 알기 위해 탐색이 필요하다. 이것을 동적 메서드 탐색이라 한다.

  1. 메시지를 수신한 객체는 먼저 자신을 생성한 클래스에 적합한 메서드가 존재하는지 검사한다. 존재하면 메서드를 실행하고 탐색을 종료한다.
  2. 메서드를 찾지 못했다면 부모 클래스에서 메서드 탐색을 계속한다. 이 과정은 적합한 메서드를 찾을 때까지 상속 계층을 따라 올라가며 계속된다.
  3. 상속 계층의 가장 최상위 클래스에 이르렀지만 메서드를 발견하지 못한 경우 예외를 발생시키며 탐색을 중단한다.

책에서는 위 과정들을 예시를 통해 상세하게 설명해 주며 위임이라는 표현도 소개한다.

위임의 경우 요청받은 일을 그대로 다른 이에게 요청하여 처리하는 것을 말한다.

질문을 받았을 때 질문의 답을 챗GPT에게 물어보는 것에 비유할 수 있을 거 같다.

 

과거에는 상속을 통해 다형성을 구현하였지만 이후에는 상속이 없더라도 위임을 통해 구현할 수 있게 되었다. 책에서는 JS코드를 통해 상속 없이 다형성을 구현하는 모습을 보여준다.

위임의 경우 수신한 객체의 인스턴스를 인자로 넘겨준다고 보았는데 JS예시는 딱히 파라미터에 인스턴스를 담지 않고 있어서 좀 헷갈렸다. 위임 부분은 다시 읽어보야겠다.

 

이번 장을 통해 다형성의 4가지(파라미터, 오버로딩, 강제, 포함) 유형을 알 수 있었고 다형성의 주요 특징 업캐스팅, 동적바인딩, 동적 메서드 탐색을 알 수 있었다. 이를 통해 다형성을 만들어 냄도 알 수 있었다.

이전에 동적바인딩에 대해 좀 더 막연하게 생각하고 있었는데 이미지를 통해 메서드가 자신이 정의된 클래스를 찾아가는 그림을 보며 이해할 수 있었다.

 

C++에서는 메서드 오버로딩이 같은 계층(자식계층이면 자식, 부모면 부모 둘 중 하나만 가능)에서만 된다는 점은 몰랐기에 신선했고 Ruby, Java, C++, Javascript 등 여러 언어가 한 장에 나왔고 각 언어별 특성을 알고 있어야 표현 가능한 부분들이었기에 저자분의 실력을 다시 한번 더 느낄 수 있었다.

 

스핑크스의 수수께끼에서 아침에는 다리 4개, 점심에는 2개, 저녁에는 3개인 것도 다형성이지 않을까 싶다.

출처 및 참고자료

조영호, 『오브젝트: 코드로 이해하는 객체지향 설계』, 위키북스(2019)