为动态 Fns 实现特征
implementing traits for dyn Fns
今天我在研究函数特征。虽然我在下面展示的示例实际上可能不是很有用,但我确实想知道为什么它不能编译。
pub fn do_something(o: &(dyn Other + 'static)) {
}
trait Other {
fn do_something_other(&self);
}
impl<A> Other for dyn Fn(A) {
fn do_something_other(&self) {
do_something(self);
}
}
这里我实现了一个函数类型的特征。此函数类型在其参数上是通用的。这意味着如果你这样做:
pub fn do_something(o: &(dyn Other + 'static)) {
}
trait Other {
fn do_something_other(&self);
}
impl<F, A> Other for F where F: (Fn(A)) + 'static {
fn do_something_other(&self) {
do_something(self);
}
}
您收到一条错误消息,指出类型参数不受约束。
我明白了,但我不相信用泛型可以做到这一点。但是动态的方式,为什么不行呢?它给出以下错误:
我不明白这个错误。它声明我传递了 Fn(A) -> ()
,它没有实现 Other
。但是,这个错误确实发生在中 Other
的实现中。怎么不能在这里实现呢?
我的第一个想法是因为每个闭包都是它自己的类型。如果和这个有关,我觉得这个错误很奇怪。
第一个构造失败,因为您无法将 &dyn A
转换为 &dyn B
,即使在为 dyn A
.
实现 B
时也是如此
trait A {}
trait B {
fn do_thing(&self);
}
impl B for dyn A {
fn do_thing(&self) {
let b: &dyn B = self;
}
}
error[E0308]: mismatched types
--> src/lib.rs:9:25
|
9 | let b: &dyn B = self;
| ------ ^^^^ expected trait `B`, found trait `A`
| |
| expected due to this
|
= note: expected reference `&dyn B`
found reference `&(dyn A + 'static)`
好吧,您可以转换特征,但只能在源特征的帮助下进行。但是由于在这种情况下源是 Fn
,所以那不是路由。
第二个构造失败,因为 Rust 不允许您实现可能发生冲突的特征。尝试为实现 A<_>
的类型实现 B
将自动被拒绝,因为类型可以有多个 A<_>
.
的实现
trait A<T> {}
trait B {
fn do_thing(&self);
}
impl<T, U> B for T where T: A<U> {
fn do_thing(&self) {}
}
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:7:9
|
7 | impl<T, U> B for T where T: A<U> {
| ^ unconstrained type parameter
特别是关于 Fn
s,它有点难以分辨,因为通常函数 objects 只实现一个 Fn
特征。但是,关键字通常是 ,因为您可以在夜间启用一项功能来做到这一点。而且特质系统通常不玩收藏夹
那你能做什么?好吧,第一个方法仍然是 functional,只是你必须将实现保持在 trait 内。如果您对函数参数使用具体类型,则可以使用第二种方法。
您可以为 &dyn Fn(_)
实现 Other
(在引用上实现它而不是 object 本身)。但这对于通常使用 Fn
object 的方式来说并不是特别方便。
pub fn do_something(o: &dyn Other) {}
trait Other {
fn do_something_other(&self);
}
impl<A> Other for &dyn Fn(A) {
fn do_something_other(&self) {
do_something(self);
}
}
fn main() {
// THIS WORKS
let closure: &dyn Fn(_) = &|x: i32| println!("x: {}", x);
closure.do_something_other();
// THIS DOESN'T WORK
// let closure = |x: i32| println!("x: {}", x);
// closure.do_something_other();
}
另一种选择是使 Other
特征通用以约束 A
,但这当然取决于它的设计使用方式。
今天我在研究函数特征。虽然我在下面展示的示例实际上可能不是很有用,但我确实想知道为什么它不能编译。
pub fn do_something(o: &(dyn Other + 'static)) {
}
trait Other {
fn do_something_other(&self);
}
impl<A> Other for dyn Fn(A) {
fn do_something_other(&self) {
do_something(self);
}
}
这里我实现了一个函数类型的特征。此函数类型在其参数上是通用的。这意味着如果你这样做:
pub fn do_something(o: &(dyn Other + 'static)) {
}
trait Other {
fn do_something_other(&self);
}
impl<F, A> Other for F where F: (Fn(A)) + 'static {
fn do_something_other(&self) {
do_something(self);
}
}
您收到一条错误消息,指出类型参数不受约束。
我明白了,但我不相信用泛型可以做到这一点。但是动态的方式,为什么不行呢?它给出以下错误:
我不明白这个错误。它声明我传递了 Fn(A) -> ()
,它没有实现 Other
。但是,这个错误确实发生在中 Other
的实现中。怎么不能在这里实现呢?
我的第一个想法是因为每个闭包都是它自己的类型。如果和这个有关,我觉得这个错误很奇怪。
第一个构造失败,因为您无法将 &dyn A
转换为 &dyn B
,即使在为 dyn A
.
B
时也是如此
trait A {}
trait B {
fn do_thing(&self);
}
impl B for dyn A {
fn do_thing(&self) {
let b: &dyn B = self;
}
}
error[E0308]: mismatched types
--> src/lib.rs:9:25
|
9 | let b: &dyn B = self;
| ------ ^^^^ expected trait `B`, found trait `A`
| |
| expected due to this
|
= note: expected reference `&dyn B`
found reference `&(dyn A + 'static)`
好吧,您可以转换特征,但只能在源特征的帮助下进行。但是由于在这种情况下源是 Fn
,所以那不是路由。
第二个构造失败,因为 Rust 不允许您实现可能发生冲突的特征。尝试为实现 A<_>
的类型实现 B
将自动被拒绝,因为类型可以有多个 A<_>
.
trait A<T> {}
trait B {
fn do_thing(&self);
}
impl<T, U> B for T where T: A<U> {
fn do_thing(&self) {}
}
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:7:9
|
7 | impl<T, U> B for T where T: A<U> {
| ^ unconstrained type parameter
特别是关于 Fn
s,它有点难以分辨,因为通常函数 objects 只实现一个 Fn
特征。但是,关键字通常是 ,因为您可以在夜间启用一项功能来做到这一点。而且特质系统通常不玩收藏夹
那你能做什么?好吧,第一个方法仍然是 functional,只是你必须将实现保持在 trait 内。如果您对函数参数使用具体类型,则可以使用第二种方法。
您可以为 &dyn Fn(_)
实现 Other
(在引用上实现它而不是 object 本身)。但这对于通常使用 Fn
object 的方式来说并不是特别方便。
pub fn do_something(o: &dyn Other) {}
trait Other {
fn do_something_other(&self);
}
impl<A> Other for &dyn Fn(A) {
fn do_something_other(&self) {
do_something(self);
}
}
fn main() {
// THIS WORKS
let closure: &dyn Fn(_) = &|x: i32| println!("x: {}", x);
closure.do_something_other();
// THIS DOESN'T WORK
// let closure = |x: i32| println!("x: {}", x);
// closure.do_something_other();
}
另一种选择是使 Other
特征通用以约束 A
,但这当然取决于它的设计使用方式。