如何在 Rust 中将方法用作函数指针
How to use a method as a function pointer in Rust
我有一个特征方法需要改变结构的内部数据,我希望我可以将 setter 方法作为参数传递给特征方法。我想这样做,以便我可以通过指定作为参数传递的函数来灵活地处理变异的内容。
此代码是对我正在尝试做的事情的简化,它具有相同的编译器问题。
谢谢
代码
struct MyStruct {
i: usize
}
impl MyStruct {
fn set_i(mut self, i: usize) -> Self {
self.i = i;
self
}
fn new() -> Self{
MyStruct{ i: 0 }
}
}
trait MyTrait {
fn do_some_setting(&mut self, setter_function: fn(&mut Self, usize) -> Self ) {
setter_function(&mut self, 7);
}
}
impl MyTrait for MyStruct {}
fn main() {
let mut s = MyStruct::new()
.set_i(3);
assert_eq!(s.i, 3);
s.do_some_setting(MyStruct::set_i);
assert_eq!(s.i, 7);
}
问题
error[E0308]: mismatched types
--> src/main.rs:27:23
|
27 | s.do_some_setting(MyStruct::set_i);
| ^^^^^^^^^^^^^^^ expected `&mut MyStruct`, found struct `MyStruct`
|
= note: expected fn pointer `for<'r> fn(&'r mut MyStruct, _) -> MyStruct`
found fn item `fn(MyStruct, _) -> MyStruct {MyStruct::set_i}`
这不起作用,因为 MyTrait::do_some_setting
需要第一个参数为 &mut Self
类型的函数,而 MyStruct::set_i
的第一个参数为 mut self
类型。
您可以通过将 MyStruct::set_i
的签名更改为 set_i(&mut self, i: usize)
来解决此问题,但是编译器会抱怨 mismatched types
因为它期望 MyStruct::set_i
为 return Self
但你会 returning &mut Self
。您可以在克隆后派生 Clone
和 return 结构,也可以将签名中的 return 类型更改为 &mut Self
.
编译器将再次抱怨类型不匹配,因为 MyTrait::do_some_setting
中的 setter_function
是 returns Self
的函数,而不是 &mut Self
。您必须将 setter_function
的签名更改为 return &mut Self
.
编译器现在会在 let mut s = MyStruct::new().set_i(3)
处抱怨 temporary value dropped while borrowed
。您必须先创建 MyStruct
,然后在其上使用 set_i
。
最后,您将得到如下代码:
struct MyStruct {
i: usize,
}
impl MyStruct {
fn set_i(&mut self, i: usize) -> &mut Self {
self.i = i;
self
}
fn new() -> Self {
MyStruct { i: 0 }
}
}
trait MyTrait {
fn do_some_setting(&mut self, setter_function: fn(&mut Self, usize) -> &mut Self) {
setter_function(self, 7);
}
}
impl MyTrait for MyStruct {}
fn main() {
let mut s = MyStruct::new();
s.set_i(3);
assert_eq!(s.i, 3);
s.do_some_setting(MyStruct::set_i);
assert_eq!(s.i, 7);
}
我有一个特征方法需要改变结构的内部数据,我希望我可以将 setter 方法作为参数传递给特征方法。我想这样做,以便我可以通过指定作为参数传递的函数来灵活地处理变异的内容。
此代码是对我正在尝试做的事情的简化,它具有相同的编译器问题。
谢谢
代码
struct MyStruct {
i: usize
}
impl MyStruct {
fn set_i(mut self, i: usize) -> Self {
self.i = i;
self
}
fn new() -> Self{
MyStruct{ i: 0 }
}
}
trait MyTrait {
fn do_some_setting(&mut self, setter_function: fn(&mut Self, usize) -> Self ) {
setter_function(&mut self, 7);
}
}
impl MyTrait for MyStruct {}
fn main() {
let mut s = MyStruct::new()
.set_i(3);
assert_eq!(s.i, 3);
s.do_some_setting(MyStruct::set_i);
assert_eq!(s.i, 7);
}
问题
error[E0308]: mismatched types
--> src/main.rs:27:23
|
27 | s.do_some_setting(MyStruct::set_i);
| ^^^^^^^^^^^^^^^ expected `&mut MyStruct`, found struct `MyStruct`
|
= note: expected fn pointer `for<'r> fn(&'r mut MyStruct, _) -> MyStruct`
found fn item `fn(MyStruct, _) -> MyStruct {MyStruct::set_i}`
这不起作用,因为 MyTrait::do_some_setting
需要第一个参数为 &mut Self
类型的函数,而 MyStruct::set_i
的第一个参数为 mut self
类型。
您可以通过将 MyStruct::set_i
的签名更改为 set_i(&mut self, i: usize)
来解决此问题,但是编译器会抱怨 mismatched types
因为它期望 MyStruct::set_i
为 return Self
但你会 returning &mut Self
。您可以在克隆后派生 Clone
和 return 结构,也可以将签名中的 return 类型更改为 &mut Self
.
编译器将再次抱怨类型不匹配,因为 MyTrait::do_some_setting
中的 setter_function
是 returns Self
的函数,而不是 &mut Self
。您必须将 setter_function
的签名更改为 return &mut Self
.
编译器现在会在 let mut s = MyStruct::new().set_i(3)
处抱怨 temporary value dropped while borrowed
。您必须先创建 MyStruct
,然后在其上使用 set_i
。
最后,您将得到如下代码:
struct MyStruct {
i: usize,
}
impl MyStruct {
fn set_i(&mut self, i: usize) -> &mut Self {
self.i = i;
self
}
fn new() -> Self {
MyStruct { i: 0 }
}
}
trait MyTrait {
fn do_some_setting(&mut self, setter_function: fn(&mut Self, usize) -> &mut Self) {
setter_function(self, 7);
}
}
impl MyTrait for MyStruct {}
fn main() {
let mut s = MyStruct::new();
s.set_i(3);
assert_eq!(s.i, 3);
s.do_some_setting(MyStruct::set_i);
assert_eq!(s.i, 7);
}