[types] 관련 유형과 제네릭 유형을 사용하는 것이 적절한시기는 언제입니까?

에서 이 질문 , 문제는 그 연관된 유형에 제네릭 형식 매개 변수를 사용을 시도 변경하여 해결할 수 일어났다. 이로 인해 “여기서 관련 유형이 더 적합한 이유는 무엇입니까?”라는 질문을하게되었고 더 많은 것을 알고 싶었습니다.

관련 유형을 도입RFC 는 다음 같이 말합니다.

이 RFC는 다음을 통해 특성 일치를 명확히합니다.

  • 모든 형질 타입 파라미터 치료 입력 유형
  • 출력 유형 인 연관된 유형 제공 .

RFC는 동기를 부여하는 예제로 그래프 구조를 사용 하며 문서 에서도 사용 되지만 유형 매개 변수화 된 버전에 비해 관련 유형 버전의 이점을 충분히 이해하지 못함을 인정합니다. 가장 중요한 것은 distance메서드가 Edge유형 에 대해 신경 쓸 필요가 없다는 것입니다 . 이것은 좋지만 관련 유형을 갖는 이유가 조금 얕아 보입니다.

관련 유형이 실제로 사용하기에 매우 직관적이라는 것을 알았지 만 내 API에서 언제 어디서 사용해야할지 결정할 때 어려움을 겪고 있습니다.

코드를 작성할 때 제네릭 유형 매개 변수보다 연관된 유형을 언제 선택해야하고 언제 반대해야합니까?



답변

이것은 이제 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>상황에 따라? 그럼에도 불구하고 저자는 판단을 내렸고 추가를 위해 반환 유형을 오버로드 할 필요가 없다고 결정했습니다.

제 개인적인 입장은 정답이 없다는 것입니다. 그럼에도 불구하고, 단일성 인수를 넘어서, 연관된 유형은 지정해야하는 매개 변수의 수를 줄임으로써 특성을 사용하는 것을 더 쉽게 만든다고 언급하고 싶습니다. 따라서 일반 특성 매개 변수를 사용하는 유연성의 이점이 명확하지 않은 경우에 대비하여 관련 유형으로 시작하는 것이 좋습니다.


답변

관련 유형은 그룹화 메커니즘 이므로 유형을 함께 그룹화하는 것이 합리적 일 때 사용해야합니다.

Graph문서에 소개 된 특성은이의 예입니다. 는 Graph일반화 되기를 원 하지만 특정 종류의을 갖게 Graph되면 Node또는 Edge유형이 더 이상 변경 되는 것을 원하지 않습니다. 특정 사람 Graph은 단일 구현 내에서 이러한 유형을 변경하고 싶지 않으며 실제로 항상 동일하기를 원합니다. 그들은 함께 그룹화되거나 심지어 연관 이라고 말할 수 있습니다 .


답변