我在 Rust 用户论坛上发现了这个问题:泛型:我可以说“每个元素都是 FromSql 的元组”。基本上,问题是知道如何做这样的事情:
trait Foo {}
struct A {}
impl Foo for A {}
struct B {}
impl Foo for B {}
fn main() {
let x = (A{}, A{}, B{}, A{});
bar(x);
}
fn bar<T: Foo>(tuple: (T...)) {
}
这段代码不起作用,这是一个想法。
那么,我们该怎么做呢?
ToAny
特性,它将应用于我们所有的结构。use std::any::Any;
pub trait ToAny {
fn as_any(&self) -> &dyn Any;
}
trait Foo: ToAny {}
它需要实现
ToAny
特性来强制每个实现Foo
的结构也实现ToAny
。
struct A {
id: i32,
}
impl ToAny for A {
fn as_any(&self) -> &dyn Any {
self
}
}
impl Foo for A {}
struct B {
id: i32,
}
impl ToAny for B {
fn as_any(&self) -> &dyn Any {
self
}
}
impl Foo for B {}
ToAny
的实现总是相同的,我们可以创建一个宏来轻松实现它。
Vec
代替元组来存储我们的值:let boxeds: Vec<Box<dyn A>> = vec![
Box::new(A {id: 1}),
Box::new(B {id: 2}),
Box::new(A {id: 3}),
Box::new(B {id: 4}),
];
// Stores the values being `B`.
let mut bees: Vec<&B> = vec![];
for boxed in &boxeds {
// `Some(x)` if `boxed` contains a `B` value.
let found = match boxed.as_any().downcast_ref::<B>() {
Some(b) => b,
None => {}, // it is a `A` value.
};
bees.push(found);
}
assert_eq!(bees, vec![
&B {id: 2},
&B {id: 4}
]);
如果我们参考问题,下面的代码:
fn bar<T: Foo>(tuple: (T...)) {
}
可以是这个有效代码:
fn bar(values: Vec<Box<dyn Foo>>) {
}
我已经写了一个要点文件正在为此进行测试。小心,我在这篇文章中更改了名称,Foo
是 A
并且只有 B
结构。