rust - 是否可以在闭包参数中使用 'downcast' 特征对象?

标签 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,似乎应该可以将指针传递给此函数。

是否有可能以某种方式将函数指针“向下转换”为 &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/

相关文章:

string - Rust 中不区分大小写的字符串匹配

rust - Rust 中有队列和堆栈集合吗?

reference - 引用如何在绑定(bind)表达式的模式中工作?

rust - 所有 Rust 属性都是宏吗?

rust - Rust 中有 POD 类型的概念吗?

scope - C++ 的 shared_ptr 在 Rust 中的等价物是什么?

filter - 为什么我的迭代器过滤器中针对泛型类型的比较操作不起作用?

rust - Github Actions + 私有(private)存储库无法正常工作

rust - 如何将 SystemTime::now() 转换为整数类型?

multithreading - 如何从另一个线程终止或挂起 Rust 线​​程?