我有一个带有泛型类型参数的特征。我想将实现此特征的不同对象放入一个集合中。对象有不同的类型参数。
当我这样做时,编译器告诉我需要指定泛型类型参数。实际上,我的情况不需要这种通用类型信息,因此某种通配符适合我。让我展示代码,因为它更好地表明了我的意图:
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
()
});
}
Run Code Online (Sandbox Code Playgroud)
错误是:
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>`
Run Code Online (Sandbox Code Playgroud)
我明白为什么编译器给我这个错误:我把 Foo 放在第一位,它有 i64 作为类型参数。之后,编译器只期望 i64 作为类型参数。但有没有办法解决这个问题呢?
我认为你不能让它完全像这样工作。
要实现类似的结果,您可以选择让您的元素实现另一个非通用特征,然后Vec如果您事先不知道最终T可能的类型,则将其添加到您的元素中,即该特征是您的公共 API 和其他板条箱的一部分预计会为自己的类型实现它T。
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
()
});
}
Run Code Online (Sandbox Code Playgroud)
T或者,如果您提前知道所有可能的类型,您可以将T特征中的 更改为包含您想要支持的所有类型的枚举:
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
()
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
850 次 |
| 最近记录: |