trait Counter {
fn count(&self) -> i32;
}
struct AddCounter {
a: i32,
b: i32,
}
impl Counter for AddCounter {
fn count(&self) -> i32 {
self.a + self.b
}
}
struct MulCounter {
a: i32,
b: i32,
}
impl Counter for MulCounter {
fn count(&self) -> i32 {
self.a * self.b
}
}
fn get_counter(a: i32, b: i32, op: &str) -> impl Counter {
match op {
"+" => AddCounter { a, b },
"*" => MulCounter { a, b },
_ => panic!(format!("{}{}", "未知的符号:", op)),
}
}
fn main() {}
致电get_counter(...)
时出现错误:
error[E0308]: match arms have incompatible types
--> src/main.rs:26:5
|
26 | / match op {
27 | | "+" => AddCounter { a, b },
28 | | "*" => MulCounter { a, b },
| | ------------------- match arm with an incompatible type
29 | | _ => panic!(format!("{}{}", "未知的符号:", op)),
30 | | }
| |_____^ expected struct `AddCounter`, found struct `MulCounter`
|
= note: expected type `AddCounter`
found type `MulCounter`
答案 0 :(得分:6)
请参见impl Trait
符号作为通用类型。您不能写:
fn get_counter<T>(a: i32, b: i32, op: &str) -> T {
match op {
"+" => AddCounter { a, b },
"*" => MulCounter { a, b },
_ => panic!(format!("{}{}", "未知的符号:", op)),
}
}
因为AddCounter
和MulCounter
的类型不同:T
是什么?
您可以使用动态调度代替静态调度:
fn get_counter(a: i32, b: i32, op: &str) -> Box<dyn Counter> {
match op {
"+" => Box::new(AddCounter { a, b }),
"*" => Box::new(MulCounter { a, b }),
_ => panic!(format!("{}{}", "未知的符号:", op)),
}
}
使用静态分派时,Rust编译器使代码单态化:它为泛型类型的每个值生成一个新函数(有关更多详细信息,请参见What is monomorphisation with context to C++?)。这些返回值中的每一个都是“真实”普通类型。在这种情况下,函数无法在一个路径中返回(例如)String
,而在另一路径中返回i32
。
在dynamic dispatch的情况下,返回的不是“真实”类型,而是一个特征对象:编译器不知道真实类型;它只关心trait对象可以用作trait实现者。这就是您的需要。