[Rust] 동적 디스패치 (번역)

먼저 이전 포스팅을 참조하길 바란다.
https://m.blog.naver.com/sssang97/221681140178

러스트는 트레잇 객체라 불리는 기능을 통해 동적 디스패치를 구현한다.

Foo라는 타입이 있을 경우, &Foo나 Box 등을 트레잇 객체 타입이라고 한다. 이러한 녀석들은 런타임에만 실제 타입을 알 수 있다.

트레잇 객체는 포인터를 통해 트레잇을 구현한 구상 타입을 해당 트레잇 타입으로 캐스팅하거나(예: &x as &Foo), 트레잇 타입의 매개변수로 강제전달(coercion)할때 생성된다.

이러한 트레잇 객체의 강제전달(coercions)과 캐스팅은 &mut T -> &mut Foo와, Box -> Box 형태의 포인터들에 대해서도 잘 동작한다.
강제전달과 캐스팅은 이런 점에서는 동등하다.

이러한 동작은 포인터의 타입에 대한 컴파일러의 지식을 '지우는' 것처럼 보인다.
이런 이유로 트레잇 객체를 가리켜 '타입 지우개'라고 부르기도 한다.

다시 위의 예제로 돌아가보자. 이제 우리는 트레잇 객체를 얻어서 동적 디스패치를 수행하도록 할 수 있다.


**fn do_something(x: &Foo) **
**{ **
**    x.method(); **
**} **

**fn main() **
**{ **
**    let x = 5u8; **
**    do_something(&x as &Foo); **
**} **

혹은 강제전달로

**fn do_something(x: &Foo) **
**{ **
**    x.method(); **
**} **

**fn main() **
**{ **
**    let x = "Hello".to_string(); **
**    do_something(&x); **
**} **

트레잇 객체를 받는 함수는 Foo를 구현하는 각각의 타입들에 대해서는 알고 있는게 없다.

그래서 정적 디스패치와는 다르게 하나의 복사본만이 생성되고, 대체로 더 적은 코드를 결과로 뱉는다.(아닐수도 있다.)

하지만, 이런저런 추가 비용들이 좀 따른다.
더 느린 가상함수를 호출해야 하고,
함수 인라인이나 관련 최적화들을 억제해야 하기 때문이다.


https://doc.rust-lang.org/1.30.0/book/first-edition/trait-objects.html#representation