Generics 一般特征对象向量

Generics 一般特征对象向量,generics,types,enums,rust,polymorphism,Generics,Types,Enums,Rust,Polymorphism,(这是我第二次尝试追踪我的确切问题。请参阅编辑历史记录) 我有一个简单的通用特性和两种不同的实现: pub trait MyTrait<T=Self> where T: MyTrait { } struct Impl1; impl MyTrait for Impl1 { } struct Impl2; impl MyTrait for Impl2 { } 每个MyTrait对象都会消耗自身,并可能导致MyEnum::a包含另一个MyTrait对象,或者MyEnum::B泛型的东

(这是我第二次尝试追踪我的确切问题。请参阅编辑历史记录)

我有一个简单的通用特性和两种不同的实现:

pub trait MyTrait<T=Self> where T: MyTrait {
}

struct Impl1;
impl MyTrait for Impl1 {
}

struct Impl2;
impl MyTrait for Impl2 {
}

每个
MyTrait
对象都会消耗自身,并可能导致
MyEnum::a
包含另一个
MyTrait
对象,或者
MyEnum::B

泛型的东西不管特征、类型或函数是否是可以处理的代码,但仅仅是在替换它们时生成代码的模板。所以它们不是“对象安全的”,也就是说,您不能将它们用于动态引用和智能指针的类型。您只能使用它们的特定实例

MyTrait
是通用的,因此您不能使用
&dyn MyTrait
框。您只能使用
&dyn MyTrait

您确实有参数的默认值,但是
Self
是特殊的,因为
Self
是实现特征的类型,因此只有在
impl
定义中才有意义。但不是在试图声明
Vec
的自由函数中。这就是为什么它不能被编译

另外,由于自身的特殊性,
impl MyTrait for Impl1
被删除为
impl MyTrait for Impl1
impl MyTrait for Impl2
被删除为
impl MyTrait for Impl2
。由于
MyTrait
MyTrait
是不同的特征,因此
Impl1
Impl2
没有可用于将它们装箱并放入公共向量中的公共特征


动态多态性需要一个具体的、非泛型的trait。

MyTrait
中泛型参数的用途是什么?在特质中你在哪里使用了T?编辑表明你脑子里有一个问题,但你没有解释,只是展示了具体的、失败的、试图解决它的尝试。试着描述更高层次的问题,这样我们就可以试着引导您找到对此首选的解决方案
dyn Trait
enum
s各有优缺点,您应该使用哪一种取决于您更广泛的需求。广告编辑:但实现什么?混合使用静态(泛型)和动态(特征对象、枚举)多态性效果不佳。你需要想出另一个表示法,如果他们不知道它应该是什么,没有人能帮助你。
fn foo() {
    let mut traits: Vec<Box<MyTrait>> = Vec::new();
    traits.push(Box::new(Impl1{}));
    traits.push(Box::new(Impl2{}));
}
error[E0393]: the type parameter `T` must be explicitly specified
  --> src/main.rs:25
   |
25 |     let mut traits: Vec<Box<MyTrait>> = Vec::new();
   |                             ^^^^^^^ missing reference to `T`
   |
   = note: because of the default `Self` reference, type parameters must be specified on object types
enum MyEnum<T: MyTrait> {
    A(T),
    B
}

pub trait MyTrait<T=Self> where T: MyTrait {
    fn do_stuff(self) -> MyEnum<T>;
}

struct Impl1;
impl MyTrait for Impl1 {
    fn do_stuff(self) -> MyEnum<Impl1> {
        MyEnum::A(self)
    }
}

struct Impl2;
impl MyTrait for Impl2 {
    fn do_stuff(self) -> MyEnum<Impl2> {
        MyEnum::B
    }
}