OOP to Rust

상속 대체 설계

러스트는 부모 구조체의 필드와 메서드를 그대로 물려받는 상속 대신, 코드 공유와 다형성의 목적을 별도 도구로 표현합니다.

상속으로 얻고 싶던 것을 나누어 고른다

의도별 대안
원래 의도
러스트 대안
어떻게 표현하나
피하는 문제
공통 동작 재사용 부모 메서드를 여러 타입에서 쓰고 싶음
trait 기본 메서드 Summary 같은 공통 동작을 기본 구현으로 둡니다.
필요한 타입만 구현 각 타입은 필요한 동작만 선택해 구현하거나 덮어씁니다.
불필요한 부모 API 노출 맞지 않는 메서드를 계층 때문에 떠안지 않습니다.
같은 자리에서 사용 서로 다른 구체 타입을 같은 인터페이스로 다룸
제네릭 또는 트레이트 객체 컴파일타임이면 bound, 런타임이면 dyn Trait를 씁니다.
필요 능력만 제약 인자가 실제로 요구하는 동작만 타입 경계에 적습니다.
깊은 타입 계층 상속 트리 대신 사용 위치의 요구사항이 드러납니다.
필드와 상태 공유 부모 필드를 하위 타입에 물려주고 싶음
composition 공통 상태를 별도 구조체로 만들고 필드로 포함합니다.
소유 관계를 명시 어떤 타입이 어떤 상태를 갖는지 구조체 필드로 보입니다.
암묵적 결합 부모 변경이 하위 타입 전체로 번지는 위험을 줄입니다.

상속을 선택하는 이유

reuse

구현 재사용

부모 타입의 메서드 구현을 여러 하위 타입에서 다시 쓰고 싶습니다.

poly

같은 자리에서 사용

서로 다른 타입을 같은 인터페이스를 가진 값처럼 다루고 싶습니다.

risk

불필요한 공유 위험

하위 타입에 맞지 않는 메서드까지 함께 노출될 수 있습니다.

limit

설계 유연성 감소

단일 상속 구조에서는 조합보다 계층을 먼저 맞추게 됩니다.

러스트 대안

trait

기본 트레이트 메서드

Summary처럼 공통 동작을 기본 구현으로 제공하고 필요하면 오버라이드합니다.

bound

제네릭과 트레이트 바운드

필요한 능력만 제약으로 걸어 범주 내 매개변수형 다형성을 얻습니다.

object

트레이트 객체

런타임에 여러 구체 타입을 같은 인터페이스 뒤에 숨길 수 있습니다.

api

명시적 공개 API

캡슐화와 조합을 유지하면서 필요한 동작만 외부에 공개합니다.

핵심 정리

러스트의 선택은 상속을 없애는 데서 끝나지 않습니다. 공유할 동작, 대체 가능한 타입, 감출 구현을 각각 다른 문법으로 드러내 설계 의도를 더 좁게 표현합니다.