40
이펙티브 러스트
와 비슷하다. 러스트에서 내부적으로
vtable
을 이용한다는 점도
C
++와 거의 비슷하다.
이런 동적인 특성 때문에 트레이트 객체를 레퍼런스 (예:
&
dyn
Trait
)나 포인터 (예:
Box
<
dyn
Trait
>
) 등을 통해 간접적으로 처리해야 한다. 컴파일 시점에는 트레이트를 구현하는 객체의
크기를 알 수 없기 때문이다 (거대한
struct
일 수도 있고, 조그만
enum
일 수도 있다 ). 따라서
원시 트레이트 객체를 할당하는 데 필요한 공간 크기를 정확히 알 방법이 없다.
객체의 크기를 정확히 모른다는 말은 트레이트 객체로 사용되는 트레이트가
Self
타입을 반환
하는 함수를 가질 수 없거나, 메서드가 호출되는 객체인 수신자
receiver
말고는
Self
를 사용하는
인수를 가질 수 없다는 뜻이기도 하다. 그 이유는 트레이트 객체를 사용하도록 사전에 컴파일
된 코드는
Self
가 얼마나 큰지 전혀 알 수 없기 때문이다.
fn
some
_
fn
<
T
>(
t
:
T
)
와 같은 제네릭 함수를 가진 트레이트는 존재할 수 있는 모든
T
타입에
대해 구현할 수 있는 함수가 무한하다. 트레이트 바운드로 사용할 거라면 그래도 괜찮다. 호출
될 가능성이 있는 제네릭 함수가 무한히 많더라도, 컴파일 타임에 실제로 호출되는 제네릭 함
수는 유한하기 때문이다. 하지만 트레이트 객체는 그렇지 않다. 컴파일 타임에 코드를 생성할
때, 런타임에 올 수 있는 모든
T
를 처리할 수 있게 만들어야 하기 때문이다.
Self
와 제네릭 함수를 사용할 수 없다는 제약 ...