본문 바로가기
Computer Science

상속, A is B, A behaves as B, 리스코프 치환 원칙

by invrtd.h 2024. 1. 30.

 

 객체 지향 프로그래밍은 인간이 사물이나 개념들을 서로 연관 짓는 방식을 프로그래밍 언어로 그대로 표현할 수 있게 함으로써 코드의 가독성을 높인다. 여기서 자주 쓰이는 "연관 짓는 방식"에는 다음과 같은 것들이 있다.

  • 포함 관계 (A is B)
    • 예제: 사람동물이다.
    • 프로그래밍 언어에서 상속이라는 기능을 쓰면 포함 관계를 표현할 수 있다.
    • 다음 프로그래밍 언어 "public class Human extends Animal"은 적법한 코드다. 사람은 동물이기 때문이다. 그러나 위 짤방에 나온 "public class Car extends Person"은 좋은 코드가 아니다.
  • 개체 관계 (a is an instance of B)
    • 예제: 박은빈사람이다.
    • 프로그래밍 언어에서 클래스와 인스턴스 사이의 관계가 바로 이 개체 관계를 모델링하는 것이다.
      • 이 관점을 지지하는 사람들은 "인스턴스는 붕어빵이고 클래스는 붕어빵틀이에요~" 같은 설명을 그다지 좋아하지 않는다.
    • 한국어로 포함 관계와 개체 관계는 모두 '-은 -다' 문법으로 표현되지만 둘은 엄연히 구별되어야 한다. 포함 관계에서 A와 B는 모두 클래스지만, 개체 관계에서 a는 인스턴스고 B는 클래스다. 인스턴스는 명확한 실체를 가졌지만, 클래스는 물리적 실체 없는 여러 인스턴스의 집합일 뿐이며 추상적인 개념이다.
    • 영어 화자들은 인스턴스와 클래스를 각각 관사 the와 a로 구별하는 듯하다. 나는 영어가 모국어가 아니라 잘 모른다.
  • 부분 관계 (A has B)
    • 예제: 자동차에는 핸들이 달려 있다.
    • 프로그래밍 언어에서 클래스 A가 멤버 b를 가지고 그 타입이 B라면, 부분 관계를 모델링한 것이 된다.
    • 마찬가지로 "public class Handle extends Car"는 좋은 코드가 아니다. "public class Car { private Handle h; }"가 더 적절할 것이다.

 객체 지향 프로그래밍을 처음 하는 사람들은 여러 사물 또는 개념 사이의 관계를 포함/개체/부분 셋 중 하나로 분류하는 것에 익숙하지 않기 때문에 "public class Car extends Person" 같은 실수를 저지른다. 좋은 코드를 작성하기 위해서는 관계들을 적절하게 분류하는 모델링 훈련이 필요할 것이다.

 

 문제는 상속이라는 OOP 개념이 "A is B" 관계를 적절히 표현한 것이 아니라는 주장이 계속해서 나오고 있다는 것이다. 이를 이해하기 위해 다음 반례를 살펴보자.

 

  • 정사각형직사각형이다.
  • 이 문장은 참이며, 포함 관계(A is B)를 나타낸다. 정사각형과 직사각형 모두 클래스다.
  • 그러나 이를 상속이라는 기능을 사용하여 나타내는 데 애로사항이 있다. Square 클래스가 Rectangle 클래스를 상속했다고 가정해 보자. Rectangle 클래스에 resizeHeight() 메서드가 있어서 이것을 호출하면 높이를 재조정하는 기능을 구현했다고 하자. 그러면 Sqaure 클래스에도 resizeHeight() 기능이 있어야 한다. 그러나 이 기능이 무엇을 말하는지 확실하지 않다. 정사각형은 가로와 세로가 같아야 하는데 resizeHeight()를 호출하면 더 이상 정사각형이 정사각형이 아닐 것처럼 보인다.
  • 따라서 정사각형-직사각형 관계는 상속을 통해 모델링하기 적절하지 않다.

 이 문제를 해결하기 위해 객체 지향 프로그래밍 5원칙 중 하나로 리스코프 치환 원칙이 제시되었다. B가 A를 상속한다면, B의 인스턴스 b는 A의 인스턴스 a가 할 수 있는 일을 다 할 수 있어야 한다는 원칙이다. 위 정사각형-직사각형 관계는 정사각형이 직사각형이 할 수 있는 일(세로 길이 늘리기)을 할 수 없으므로 리스코프 치환 원칙을 위배한다. 시간이 지나면서 리스코프 치환이 가능한 관계들도 위 세 관계처럼 깔끔한 이름이 붙게 되었다. 그 이름이 바로 "A behaves as B", 즉 "A는 B처럼 행동한다"다.

 

 따라서 현대적인 관점에 따르면 상속은 "A is B"를 모델링하는 기능이 아니라 "A behaves as B"를 모델링하는 기능이다. 그러나 이것이 상속할 때 "A is B"를 간과해도 된다는 뜻은 아니다. A가 B를 상속할 수 있는지 없는지 판별하기 위해 A is B가 성립하는지 아닌지 따져보는 것은 여전히 압도적인 편리성을 제공해줄 것이다.

'Computer Science' 카테고리의 다른 글

Mac에서 Launchpad가 하단 바에서 디폴트로 안 보일 때 해결법  (0) 2024.03.20
흑흑흑  (0) 2023.12.15
흑흑  (0) 2023.12.13
  (0) 2023.12.12
Bomb Lab에 꼭 필요한 gdb 커맨드 모음  (0) 2023.10.08

댓글