rust 如何将一个性状的类型删除并与类型相关联?

cu6pst1q  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(112)

假设有一个集合trait,它的项有一个关联的类型:

trait CollectionItem {
    // ...
}

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

我能不能把它类型擦除到一个对CollectionCollectionItem trait都使用动态调度的类型中?也就是说,把它 Package 成如下所示的形式:

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

bvjveswy

bvjveswy1#

你可以添加一个私有的、类型擦除的辅助特征:

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))
    }
}

然后使用以下代码构建一个 Package 器类型:

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> {
    // ...
}

相关问题