rust - 如何制作具有关联类型的特征的类型删除版本?

标签 rust associated-types trait-objects

假设有一个集合特征,其项具有关联类型:

trait CollectionItem {
    // ...
}

trait Collection {
    type Item: CollectionItem;
    
    fn get(&self, index: usize) -> Self::Item;
    // ...
}

我能否以某种方式将其类型删除为对 CollectionCollectionItem 特征使用动态分派(dispatch)的类型?即将其包装成如下内容:

struct DynCollection(Box<dyn Collection<Item=Box<dyn CollectionItem>>>);
impl DynCollection {
  fn get(&self, index: usize) -> Box<dyn CollectionItem> {
    // ... what to do here?
  }
}
impl <C: Collection> From<C> for DynCollection {
  fn from(c: C) -> Self {
    // ... what to do here?
  }
}

Playground

最佳答案

您可以添加一个私有(private)的、类型删除的辅助特征:

trait DynCollectionCore {
    fn get_dyn(&self, index: usize) -> Box<dyn CollectionItem>;
}

impl<C> DynCollectionCore for C
where
    C: ?Sized + Collection,
    C::Item: 'static,
{
    fn get_dyn(&self, index: usize) -> Box<dyn CollectionItem> {
        Box::new(self.get(index))
    }
}

然后使用它来构建一个包装器类型:

struct DynCollection(Box<dyn DynCollectionCore>);

impl DynCollection {
    fn new<C>(inner: C) -> Self
    where
        C: Collection + 'static,
        C::Item: 'static,
    {
        Self(Box::new(inner))
    }
}

impl Collection for DynCollection {
    type Item = Box<dyn CollectionItem>;

    fn get(&self, index: usize) -> Box<dyn CollectionItem> {
        self.0.get_dyn(index)
    }
}

// note: something like this is also needed for `Box<dyn CollectionItem>:
//       CollectionItem` to be satisfied
impl<T: ?Sized + CollectionItem> CollectionItem for Box<T> {
    // ...
}

关于rust - 如何制作具有关联类型的特征的类型删除版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74806682/

相关文章:

rust - 如何实现具有具体生命周期的 FromStr?

iterator - 是否有提供 `iter()` 的特征?

swift - 隐式设置关联类型

ios - 在 Swift 中向下转换协议(protocol)

rust - 如何将 Rc<RefCell<Box<MyStruct>>> 传递给接受 Rc<RefCell<Box<dyn MyTrait>>> 的函数?

rust - 带有HashMap的“temporary value dropped while borrowed” <&str,&dyn Fn(&str)-> bool>

rust - 如何正确实现Deref + DerefMut?

rust - 操作返回 Box<Future> 时的生命周期编译器错误

rust - 如何为自定义结构类型实现 Mul Trait 以两种方式工作

rust - 数据融合中的索引