【问题标题】:How to store trait implementations together when the trait has associated types当特征具有关联类型时如何将特征实现存储在一起
【发布时间】:2021-06-23 15:08:17
【问题描述】:

当我们想将多个类型一起存储在一个集合中时,可以使用特征对象。

但是当 trait 具有关联类型时,我不知道该怎么做。

trait Error {}

trait Trait {
    type Error: Error;
    fn set(&mut self, key: String, value: String) -> Result<(), Self::Error>;
}

struct StructA;
impl Trait for StructA {
    type Error = ErrorA;
}

enum ErrorA {}
impl Error for ErrorA {}

struct StructB;
impl Trait for StructB {
    type Error = ErrorB;
}

enum ErrorB {}
impl Error for ErrorB {}

fn main() -> Result<(), Box<dyn Error>> {
    let value: Box<dyn Trait<Error = dyn Error>> = match 0 {
        0 => Box::new(StructA),
        _ => Box::new(StructB),
    };

    value.set(String::from("key"), String::from("value"))?;

    Ok(())
}

我必须在这里指定关联类型Box&lt;dyn Trait&lt;Error = _&gt;&gt;,但我不知道哪种类型适合。我试过dyn Error,但它不起作用。

【问题讨论】:

  • @user4815162342 我刚刚为 Trait 添加了一个方法

标签: generics types rust traits associated-types


【解决方案1】:

如果您可以更改Trait,则可以通过返回动态错误类型来使其对所有错误类型都是对象安全的,例如将set() 的签名更改为:

fn set(&mut self, key: String, value: String) -> Result<(), Box<dyn Error + '_>>;

但是,如果您不能更改 Trait 以使其对象安全,您仍然可以创建自己的对象安全 trait,并为实现 @ 的每种类型提供一揽子实现987654327@。例如:

trait DynamicTrait {
    fn set(&mut self, key: String, value: String) -> Result<(), Box<dyn Error + '_>>;
}

impl<T: Trait> DynamicTrait for T {
    fn set(&mut self, key: String, value: String) -> Result<(), Box<dyn Error + '_>> {
        Trait::set(self, key, value).map_err(|e| Box::new(e) as _)
    }
}

DynamicTrait 的工作方式与Trait 完全相同,但在出错时返回Box&lt;dyn Error&gt;,因此它是对象安全的。例如,这无需修改 Trait 或其实现 StructAStructB 的实现即可工作:

fn main() {
    let value: Box<dyn DynamicTrait> = match 0 {
        0 => Box::new(StructA),
        _ => Box::new(StructB),
    };
}

Playground

【讨论】:

  • 第二种解决方案对我来说似乎不错。但是这样我怎样才能将错误返回给mainplay.rust-lang.org/…
  • 您只需将+ 'static 添加到trait Error 的定义中即可编译。然后你也可以摆脱盒子里奇怪的+ '_生命周期。添加 'static 只需要错误只包含拥有的数据,这几乎是 Rust 错误的普遍要求——我只是假设你不能修改错误特征的实现,所以我不想添加绑定到我的例子。
猜你喜欢
  • 2019-12-08
  • 2018-06-10
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
  • 2020-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多