我想调用一个函数指针,它本身将特征对象作为参数:
fn invoke(x: &Fn(&WithFoo), y: &MyStruct) {
// MyStruct implements WithFoo
x(y);
}
到目前为止一切顺利。现在,我遇到的问题是如何使用带有签名的函数指针调用它,例如 &Fn(&WithFooBar)
其中特征 WithFooBar
继承自 WithFoo
。
这是我尝试执行此操作的示例代码:
trait WithFoo {
fn foo(&self);
}
trait WithFooBar: WithFoo {
fn bar(&self);
}
struct MyStruct {
}
impl WithFoo for MyStruct {
fn foo(&self) {
println!("foo");
}
}
impl WithFooBar for MyStruct {
fn bar(&self) {
println!("bar");
}
}
fn foobar_caller(wf: &WithFooBar) {
wf.foo();
wf.bar();
}
fn invoke(x: &Fn(&WithFoo), y: &MyStruct) {
x(y);
}
fn main() {
let data = MyStruct {};
invoke(&foobar_caller,&data);
}
此操作失败并出现以下编译错误:
error: type mismatch: the type `fn(&WithFooBar) {foobar_caller}` implements the trait `for<'r> std::ops::Fn<(&'r WithFooBar + 'r,)>`, but the trait `for<'r> std::ops::Fn<(&'r WithFoo + 'r,)>` is required (expected trait `WithFoo`, found trait `WithFooBar`) [--explain E0281]
我知道错误是说 &Fn(&WithFooBar)
不是 &Fn(&WithFoo)
,但考虑到 WithFooBar
特征继承来自 WithFoo
,似乎应该可以将指针传递给此函数。
是否有可能以某种方式将函数指针“向下转换”为 &Fn(&WithFoo)
类型?这两个我都试过了:
let f = &foobar_caller as &Fn(&WithFoo);
invoke(f,&data);
还有这个:
let f: &Fn(&WithFoo) = &foobar_caller;
invoke(f,&data);
但是这些尝试都不起作用。
(这个例子在 rust playground here 上。)
最佳答案
不,你不能这样做。首先,Rust 不支持将特征对象向下转换为另一个特征对象。使用 Any
特征,您可以将特征对象向下转换为基础对象的具体类型,然后获得不同类型的特征对象,但这需要知道对象的具体类型,而您不知道– 这就是特征对象的全部意义所在!
此外,您尝试做的事情并不合理:不应向期望接收 &WithFooBar
的函数传递 &WithFoo
,因为 WithFoo
可能不会实现 WithFooBar
。如果它是另一种方式,那将是合理的,但即使 WithFooBar
继承自 WithFoo
,Rust 也不允许转换 &WithFooBar
到 &WithFoo
,所以即使我们尝试创建一个包装函数,它也不会工作。
关于rust - 是否可以在闭包参数中使用 'downcast' 特征对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37634657/