Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 有可能拥有一个动态的通用特征集合吗?_Rust - Fatal编程技术网

Rust 有可能拥有一个动态的通用特征集合吗?

Rust 有可能拥有一个动态的通用特征集合吗?,rust,Rust,我有一个带有泛型类型参数的特性。我想把实现这个特性的不同对象放在一个集合中。对象具有不同的类型参数 当我这样做时,编译器告诉我需要指定泛型类型参数。实际上,我的案例不需要这个泛型类型信息,所以某种通配符对我来说是可行的。让我展示代码,因为它更好地显示了我的意图: trait Test<T> { fn test(&self) -> T; } struct Foo; struct Bar; impl Test<i64> for Foo { fn

我有一个带有泛型类型参数的特性。我想把实现这个特性的不同对象放在一个集合中。对象具有不同的类型参数

当我这样做时,编译器告诉我需要指定泛型类型参数。实际上,我的案例不需要这个泛型类型信息,所以某种通配符对我来说是可行的。让我展示代码,因为它更好地显示了我的意图:

trait Test<T> {
    fn test(&self) -> T;
}
struct Foo;
struct Bar;
impl Test<i64> for Foo {
    fn test(&self) -> i64 {
        println!("foo");
        42
    }
}
impl Test<String> for Bar {
    fn test(&self) -> String {
        println!("bar");
        "".to_string()
    }
}

fn main() {
    // I'm not going to invoke test method which uses generic type parameter.
    // So some kind of wildcard would work for me.
    // But underscore is not wildcard and this does not compile.
    let xs: Vec<Box<dyn Test<_>>> = vec![Box::new(Foo), Box::new(Bar)];
    xs.iter().map(|x| {
        // do some stuff, but not invoke Test::test() method, so I don't need type information
        ()
    });
}
错误是:

error[E0277]: the trait bound `Bar: Test<i64>` is not satisfied
  --> src/main.rs:24:57
   |
24 |     let xs: Vec<Box<dyn Test<_>>> = vec![Box::new(Foo), Box::new(Bar)];
   |                                                         ^^^^^^^^^^^^^ the trait `Test<i64>` is not implemented for `Bar`
   |
   = help: the following implementations were found:
             <Bar as Test<std::string::String>>
   = note: required for the cast to the object type `dyn Test<i64>`

我理解为什么编译器会给我这个错误:我把Foo放在第一位,它的类型参数是i64。在此之后,编译器只希望将i64作为类型参数。但是有办法解决这个问题吗?

我想你不能让它完全像这样工作

实现类似结果的选项是:要么让元素实现另一个非通用特性,如果您事先不知道T的最终可能类型,则将其添加到Vec中,即该特性是公共API的一部分,其他板条箱预计将为其自己的类型T实现它


我想你不能让它完全像这样工作

实现类似结果的选项是:要么让元素实现另一个非通用特性,如果您事先不知道T的最终可能类型,则将其添加到Vec中,即该特性是公共API的一部分,其他板条箱预计将为其自己的类型T实现它


如果你的部分特质本身在没有T的情况下是有用的,那么就做两个特质。当Foo同时实现Test和Test时,那么哪一个应该框起来作为Box使用?如果你的部分特质本身在没有T的情况下是有用的,那么就做两个特质。当Foo同时实现Test和Test时,那么哪一个应该框起来作为Box使用?还有第三个选项,形成子特征形成子特征,如在这种情况下。不是最漂亮的代码,因为到处都是PhantomData,但它很有效。这对我来说似乎很有用,但我不确定为什么需要PhantomData或者它的作用。PhantomData是区分Foo as Test和Foo as Test所必需的,当Foo同时实现这两个特性时。如果您尝试为T编写:impl Test2,它将失败,并出现一个错误,表明U是无约束的。还有第三个选项,可以生成一个子特性,如下面所示。不是最漂亮的代码,因为到处都是PhantomData,但它很有效。这对我来说似乎很有用,但我不确定为什么需要PhantomData或者它的作用。PhantomData是区分Foo as Test和Foo as Test所必需的,当Foo同时实现这两个函数时,如果您尝试为T编写:impl Test2,它将失败,并出现一个错误,表明U是无约束的。
trait NonGenericTest {}
trait Test2<T> : NonGenericTest {
    fn test(&self) -> T;
}

impl NonGenericTest for Foo{}
impl NonGenericTest for Bar{}

impl Test2<i64> for Foo {
    fn test(&self) -> i64 {
        println!("foo");
        42
    }
}
impl Test2<String> for Bar {
    fn test(&self) -> String {
        println!("bar");
        "".to_string()
    }
}
fn main()  {
    let xs: Vec<Box<dyn NonGenericTest>> = vec![Box::new(Foo), Box::new(Bar)];
    xs.iter().map(|x| {
        // do some stuff, but not invoke Test::test() method, so I don't need type information
        ()
    });
}
enum TestResult {
  ResultI64(i64),
  ResultString(String),
}

trait Test {
    fn test(&self) -> TestResult;
}
struct Foo;
struct Bar;
impl Test for Foo {
    fn test(&self) -> TestResult {
        println!("foo");
        TestResult::ResultI64(42)
    }
}
impl Test for Bar {
    fn test(&self) -> TestResult {
        println!("bar");
        TestResult::ResultString("".to_string())
    }
}
fn main(){
    let xs: Vec<Box<dyn Test>> = vec![Box::new(Foo), Box::new(Bar)];
    xs.iter().map(|x| {
        // do some stuff, but not invoke Test::test() method, so I don't need type information
        ()
    });
}