2017-12-29 26 views
2

저는 녹슨에게 매우 익숙해서 용어가 혼란 스러울 수 있습니다.연관된 유형이있는 형질을 박스에 넣는 방법?

일부 해시 작업을 위해 hashes 상자를 사용하고 런타임에 사용할 알고리즘 (sha256, sha512 등)을 동적으로 선택하고자합니다.

나는 이런 식으로 뭔가를 쓰고 싶습니다

let hasher = match "one of the algorithms" { 
    "sha256" => Box::new(Sha256::new()) as Box<Digest>, 
    "sha512" => Box::new(Sha512::new()) as Box<Digest> 
    // etc... 
}; 

나는 종류의 Digest에서 요구하는 관련 유형이 지정되지 않기 때문에 문제가 해결되지 않는 것을 얻는다. 내가 그들을 채우기 위해 시도하는 경우 :

"sha256" => Box::new(Sha256::new()) as Box<Digest<<OutputSize = U32, BlockSize = U64>>>, 

나는이 오류와 함께 왼쪽 해요 : the trait 'digest::Digest' cannot be made into an object합니다. 어쨌든 match은 다른 알고리즘이 다른 관련 유형을 가진 경우 약간 다른 유형을 반환하기 때문에이 방법은 실패 할 것이라고 생각합니다.

나는 분명한 뭔가를 놓치고 있습니까? 어떻게 특성을 구현하는 무언가의 인스턴스를 동적으로 생성 한 다음 그 것을 유지하고 특성 인터페이스를 통해 사용할 수 있습니까?

+1

관련 유형없이 실제로 필요한 인터페이스를 구현하는 래퍼 유형과 특성을 만들 수 있습니다. 권투 같은 특성은 작동합니다. – user4815162342

+0

관련 : [관련 유형별로 다른 객체의 벡터를 만들 수있는 방법은 무엇입니까?] (https://stackoverflow.com/q/28932450/155423) – Shepmaster

+1

@ user4815162342 그럴 가치가 있다고 생각합니다. – Shepmaster

답변

1

메시지는 object safety (longer article)을 말합니다. Digest trait 두 호환성이 있습니다

  1. 그것은 uses associated types (이 명시 적으로 모든 Digest 개체에 대한 호환 값으로 모든 유형 매개 변수를 설정하여 해결할 수 있습니다.)
  2. 값이 self 인 방법 (fn result(self) -> …)이 있습니다. 당신은 그것을 부를 수 없으며, 이는이 형질의 유 용성을 파괴합니다.

일단 특성 개체가 생성되면 메모리 레이아웃이나 관련 유형과 같은 해당 하위 유형별 기능에 대한 정보가 지워집니다. 형질 객체의 메소드에 대한 모든 호출은 vtable 포인터를 통해 수행됩니다. 이것은 모두 호환 가능해야 함을 의미하며 Rust는 이러한 측면에서 다를 수있는 메소드를 호출 할 수 없습니다.

해결 방법은 객체 호환 가능한 사용자 정의 래퍼 특성/어댑터를 만드는 것입니다. 이것이 최선의 구현인지 잘 모르겠습니다 만, 작동합니까? :

trait Digest { 
    type Assoc; 
    fn result(self); 
} 

struct Sha; 

impl Digest for Sha { 
    type Assoc = u8; 
    fn result(self) {} 
} 

/////////////////////////////////////////// 

trait MyWrapper { 
    fn result(&mut self); // can't be self/Sized 
} 

impl<T: Digest> MyWrapper for Option<T> { 
    fn result(&mut self) { 
     // Option::take() gives owned from non-owned 
     self.take().unwrap().result() 
    } 
} 

fn main() { 
    let mut digest: Box<MyWrapper> = Box::new(Some(Sha)); 
    digest.result(); 
} 
+0

만약'result'가'self : Box '을 [이 답안] (https://stackoverflow.com/a/46625787/1600898)으로 받아 들일 수 있는지 궁금합니다. 그런 식으로'Option'은 더이상 필요하지 않을 것이고,'result'를 두 번 호출하는 컴파일 타임 예방이 복원 될 것입니다. – user4815162342