我想调用一个函数指针,它本身将特征对象作为参数:
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
,似乎应该可以传递指向此函数的指针。
是否有可能以某种方式&#34; downcast&#34;类型&Fn(&WithFoo)
的函数指针?我试过这两个:
let f = &foobar_caller as &Fn(&WithFoo);
invoke(f,&data);
和此:
let f: &Fn(&WithFoo) = &foobar_caller;
invoke(f,&data);
但这些尝试都不起作用。
(此示例位于生锈操场here上。)
答案 0 :(得分:2)
不,你不能这样做。首先,Rust不支持将特征对象向下转换为另一个特征对象。使用Any
特征,您可以将特征对象向下转换为基础对象的具体类型,然后获取不同类型的特征对象,但这需要知道对象的具体类型,您不知道 - 这就是特质对象的整点!
此外,您尝试做的事情并不合理:期望收到&WithFooBar
的函数不应传递&WithFoo
,因为WithFoo
可能无法实现WithFooBar
1}}。如果它是相反的方式,那将是合理的,但即使WithFooBar
继承自WithFoo
,Rust也不允许将&WithFooBar
转换为&WithFoo
,所以,即使我们试图创建一个包装函数,它也行不通。