我有一个枚举。因为我希望枚举稍后包含数十个条目并进行多重分类,并且大多数相关处理将基于其所属的类别而不是枚举变体本身进行,所以我现在考虑切换到具有关联类型的特征(类别) 。 这样可以避免多个函数具有相同的匹配臂,我发现它们容易出错,尤其是因为它们会分散在整个代码中。
我设法获得了一些我喜欢的自动实现的功能(当使用宏时),这些代码在枚举情况下是不可能的:
与类别相关的代码(实际上是此MWE除外)将通过使用宏生成。但是,我找不到克隆Categorized
结构的方法。
trait Foo//: Clone Uncommenting breaks compilation because of object-safety
{
type Category: Category;
}
trait Category {}
struct A;
impl Category for A {}
// ... structs and impls like the above
#[derive(Clone, Copy)]
struct Bar;
impl Foo for Bar {
type Category = A;
}
//#[derive(Clone)] Uncommenting breaks compilation because Foo is not Clone
struct Categorized {
cat_a: Vec<Box<dyn Foo<Category = A>>>,
//cat_b: Vec<Box<dyn Foo<Category = B>>>,
}
trait Pushable<T, C>
where
T: Foo<Category = C>
{
fn push(&mut self, rend: T);
}
impl<T: 'static> Pushable<T, A> for Categorized
where
T: Foo<Category = A>
{
fn push(&mut self, v: T) {
self.cat_a.push(Box::new(v));
}
}
fn main() {
let mut cats = Categorized { cat_a: vec![] };
cats.push(Bar{});
let mut cat_a: Vec<Box<dyn Foo<Category = A>>> = Vec::new();
cat_a.push(Box::new(Bar{}));
//cat_a.clone(); Uncommenting breaks compilation because Foo is not Clone
}
我为“您必须使用枚举”感到讨厌,但是,我该如何解决呢?
编辑:尽管与建议的问题非常相似,但我无法使用该方法解决问题。为此,我必须使trait Foo
通用而不是具有关联的类型,因为克隆间接性状要么是通用的,要么具有关联的类型:
trait Foo<C>: FooBoxClone<C>
where
C: Category,
{
type Category;
}
trait FooBoxClone<C> {
fn clone_box(&self) -> Box<dyn Foo<C, Category = C>>;
}
impl<C, T> FooBoxClone<C> for T
where
T: 'static + Foo<C, Category = C> + Clone,
C: Category,
{
fn clone_box(&self) -> Box<dyn Foo<C, Category = C>> {
Box::new(self.clone())
}
}
impl<C: Category> Clone for Box<dyn Foo<C, Category = C>> {
fn clone(&self) -> Self {
FooBoxClone::clone_box(&**self)
}
}
除了编写Foo<C, Category = C>
的笨拙之外,我还能做到:
struct B;
impl Category for B {}
impl Foo<B> for Bar {
type Category = B;
}
这意味着Bar
将属于多个类别(并且为Pushable
实现了正确的B
之后,cats.push(Bar{});
需要类型注释)
相反,我还可以尝试为所有可能的Category
做一个间接特征,但是那样我会遇到另一组问题:
trait Foo {
type Category;
}
pub trait FooABoxClone {
fn clone_box(&self) -> Box<dyn Foo<Category = A>>;
}
impl<T> FooABoxClone for T
where
T: 'static + Foo<Category = A> + Clone,
{
fn clone_box(&self) -> Box<dyn Foo<Category = A>> {
Box::new(self.clone())
}
}
// Compilation error: Foo<Category = A> does not implement Clone
impl Clone for Box<dyn Foo<Category = A>> {
fn clone(&self) -> Self {
FooABoxClone::clone_box(&**self)
}
}
// Compilation error: type parameter `T` must be used as the type parameter for some local type
impl<T> Clone for Box<T>
where
T: 'static + Foo<Category = A> + Clone,
{
fn clone(&self) -> Self {
FooABoxClone::clone_box(&**self)
}
}