是否有可能“贬低”'闭包参数中的特征对象?

时间:2016-06-04 20:22:32

标签: rust

我想调用一个函数指针,它本身将特征对象作为参数:

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上。)

1 个答案:

答案 0 :(得分:2)

不,你不能这样做。首先,Rust不支持将特征对象向下转换为另一个特征对象。使用Any特征,您可以将特征对象向下转换为基础对象的具体类型,然后获取不同类型的特征对象,但这需要知道对象的具体类型,您不知道 - 这就是特质对象的整点!

此外,您尝试做的事情并不合理:期望收到&WithFooBar的函数不应传递&WithFoo,因为WithFoo可能无法实现WithFooBar 1}}。如果它是相反的方式,那将是合理的,但即使WithFooBar继承自WithFoo,Rust也不允许将&WithFooBar转换为&WithFoo,所以,即使我们试图创建一个包装函数,它也行不通。