programing tip

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

itbloger 2020. 10. 6. 07:56
반응형

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


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

관련 유형을 도입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 uses an associated type because its author thought that given the two arguments there would be a logical return type

As you can see, while Deref is an obvious usecase (technical constraint), the case of Add is less clear cut: maybe it would make sense for i32 + i32 to yield either i32 or Complex<i32> depending on the context? Nonetheless, the author exercised their judgment and decided that overloading the return type for additions was unnecessary.

My personal stance is that there is no right answer. Still, beyond the unicity argument, I would mention that associated types make using the trait easier as they decrease the number of parameters that have to be specified, so in case the benefits of the flexibility of using a regular trait parameter are not obvious, I suggest starting with an associated type.


Associated types are a grouping mechanism, so they should be used when it makes sense to group types together.

The Graph trait introduced in the documentation is an example of this. You want a Graph to be generic, but once you have a specific kind of Graph, you don't want the Node or Edge types to vary anymore. A particular Graph isn't going to want to vary those types within a single implementation, and in fact, wants them to always be the same. They're grouped together, or one might even say associated.

참고URL : https://stackoverflow.com/questions/32059370/when-is-it-appropriate-to-use-an-associated-type-versus-a-generic-type

반응형