이것은 이제 The Rust Programming Language 의 두 번째 판 에서 다루어 졌습니다. 그러나 추가로 잠수 해 보겠습니다.
더 간단한 예부터 시작하겠습니다.
특성 방법을 사용하는 것이 언제 적절합니까?
후기 바인딩 을 제공하는 방법에는 여러 가지가 있습니다 .
trait MyTrait {
fn hello_word(&self) -> String;
}
또는:
struct MyTrait<T> {
t: T,
hello_world: fn(&T) -> String,
}
impl<T> MyTrait<T> {
fn new(t: T, hello_world: fn(&T) -> String) -> MyTrait<T>;
fn hello_world(&self) -> String {
(self.hello_world)(self.t)
}
}
모든 구현 / 성능 전략을 무시하고 위의 두 발췌 부분을 통해 사용자 hello_world
는 어떻게 행동해야하는지 동적으로 지정할 수 있습니다.
한 차이 (의미)가 있다는 것이다 trait
주어진 유형의 것을 구현 보장 T
구현은 trait
, hello_world
반면 항상 동일한 동작을한다 struct
구현이 인스턴스별로 다른 동작을 갖는 수있다.
방법 사용이 적절한 지 여부는 사용 사례에 따라 다릅니다!
연관된 유형을 사용하는 것이 적절한시기는 언제입니까?
trait
위 의 방법과 유사하게 , 연관된 유형은 후기 바인딩의 한 형태이며 (컴파일시 발생하지만)의 사용자 trait
가 대체 할 유형을 지정된 인스턴스에 지정할 수 있도록합니다 . 이것이 유일한 방법은 아닙니다 (따라서 질문).
trait MyTrait {
type Return;
fn hello_world(&self) -> Self::Return;
}
또는:
trait MyTrait<Return> {
fn hello_world(&Self) -> Return;
}
위의 메서드의 후기 바인딩과 동일합니다.
- 첫 번째는 주어진
Self
하나의 Return
관련
- 두 번째는, 대신, 실행 허용
MyTrait
을 위해 Self
여러 대Return
어떤 형식이 더 적절한 지 여부는 단일성을 시행하는 것이 합당한 지 여부에 따라 다릅니다. 예를 들면 :
Deref
유니시티가 없으면 컴파일러가 추론 중에 미쳐 버릴 것이기 때문에 연관된 유형을 사용합니다.
Add
저자는 두 개의 인수가 주어지면 논리적 반환 유형이 있다고 생각했기 때문에 연관된 유형을 사용합니다.
당신이 볼 수 있듯이, 동안 Deref
이다 명백한 유스 케이스 (기술적 제약)의 경우 Add
덜 명확한입니다 : 어쩌면에 대한 의미 만들 것 i32 + i32
하나 양보 할 수 i32
또는 Complex<i32>
상황에 따라? 그럼에도 불구하고 저자는 판단을 내렸고 추가를 위해 반환 유형을 오버로드 할 필요가 없다고 결정했습니다.
제 개인적인 입장은 정답이 없다는 것입니다. 그럼에도 불구하고, 단일성 인수를 넘어서, 연관된 유형은 지정해야하는 매개 변수의 수를 줄임으로써 특성을 사용하는 것을 더 쉽게 만든다고 언급하고 싶습니다. 따라서 일반 특성 매개 변수를 사용하는 유연성의 이점이 명확하지 않은 경우에 대비하여 관련 유형으로 시작하는 것이 좋습니다.
trait/struct MyTrait/MyStruct
정확히 하나impl MyTrait for
또는impl MyStruct
. 일반적이기 때문에trait MyTrait<Return>
여러를 허용합니다impl
.Return
모든 유형이 될 수 있습니다. 일반 구조체는 동일합니다.