繁体   English   中英

如何对具有关联类型的特征进行装箱?

[英]How to Box a trait that has associated types?

我是Rust的新手,所以我可能对术语感到困惑。

我想使用哈希箱进行一些哈希处理,并且想动态选择运行时要使用的算法(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将返回略有不同的类型。

我是否缺少明显的东西? 如何动态创建实现特征的事物的实例,然后保留该事物并通过trait接口使用它?

该消息涉及对象安全较长的文章 )。 Digest特征有两个不兼容:

  1. 使用关联的类型 (可以通过将所有类型参数显式设置为与所有Digest对象兼容的值来解决)。
  2. 它有一个方法( fn result(self) -> … )按值获取self 您将无法调用它,这破坏了此特性的可用性。

创建特征对象后,将删除有关其特定于子类型的功能(如内存布局或关联的类型)的信息。 对trait对象的方法的所有调用都是通过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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM