使用自我回调
我正在尝试使用使用对象的自我参数的回调。阻止此编译的部分是self.make_sandwhich()位。我该如何做这样的事情并实际上将其编译为Rust?目的是使Thinguser能够为事物指定功能。在这种情况下,当您垃圾土豆时,用户会制作一个沙子。
pub trait Thing {
fn stuff(&self);
fn junk(&mut self);
}
pub struct Potato {
thing: Box<dyn FnMut()+Send>,
}
impl Potato {
fn new() -> Self {
Self{
thing: Box::new(||{println!("Original callback");}),
}
}
fn give_callback(&mut self, thing: Box<dyn FnMut()+Send>) {
self.thing = thing;
}
}
impl Thing for Potato {
fn stuff(&self) {
}
fn junk(&mut self) {
(self.thing)();
}
}
fn make_thing() -> Box<dyn Thing> {
Box::new(Potato::new())
}
pub trait ThingUser {
fn get_thing(&mut self) -> Option<Box<dyn Thing>>;
}
pub struct Person {
}
impl Person {
fn make_sandwhich(&self) {
println!("I made a sandwhich");
}
}
impl ThingUser for Person {
fn get_thing(&mut self) -> Option<Box<dyn Thing>> {
let mut p = Potato::new();
p.give_callback(Box::new(||{self.make_sandwhich()}));
Some(Box::new(p))
}
}
fn main() {
println!("Hello, world!");
let mut p = Potato::new();
p.stuff();
p.give_callback(Box::new(||{println!("Callback");}));
(p.thing)();
p.junk();
let mut q = make_thing();
q.junk();
let mut tu = Person{};
let used_thing = tu.get_thing();
used_thing.unwrap().junk();
}
I am trying to use a callback that uses the self parameter of an object. The part that prevents this from compiling is the self.make_sandwhich() bit. How can I do something like this and have it actually compile in rust? The objective is to make ThingUser able to specify functionality for a Thing. In this case, when you junk the potato, the user makes a sandwhich.
pub trait Thing {
fn stuff(&self);
fn junk(&mut self);
}
pub struct Potato {
thing: Box<dyn FnMut()+Send>,
}
impl Potato {
fn new() -> Self {
Self{
thing: Box::new(||{println!("Original callback");}),
}
}
fn give_callback(&mut self, thing: Box<dyn FnMut()+Send>) {
self.thing = thing;
}
}
impl Thing for Potato {
fn stuff(&self) {
}
fn junk(&mut self) {
(self.thing)();
}
}
fn make_thing() -> Box<dyn Thing> {
Box::new(Potato::new())
}
pub trait ThingUser {
fn get_thing(&mut self) -> Option<Box<dyn Thing>>;
}
pub struct Person {
}
impl Person {
fn make_sandwhich(&self) {
println!("I made a sandwhich");
}
}
impl ThingUser for Person {
fn get_thing(&mut self) -> Option<Box<dyn Thing>> {
let mut p = Potato::new();
p.give_callback(Box::new(||{self.make_sandwhich()}));
Some(Box::new(p))
}
}
fn main() {
println!("Hello, world!");
let mut p = Potato::new();
p.stuff();
p.give_callback(Box::new(||{println!("Callback");}));
(p.thing)();
p.junk();
let mut q = make_thing();
q.junk();
let mut tu = Person{};
let used_thing = tu.get_thing();
used_thing.unwrap().junk();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您发布的设计无法正常工作。在
Thinguser :: get_thing
中采用&amp; mut self
,这意味着self
是类型&amp; mut dyn thinguser的借用
。闭合|| {self.make_sandwhich()}
还必须借用self
(尽管它只需要非 -mut
&amp; dyn thinguser
to调用make_sand
)。self
的借用只要封闭生活就必须生存。但是,您想将封闭存储在
马铃薯
中。这意味着在存储马铃薯
也是借用的&amp; thiteuser
,但是马铃薯
根本没有定义任何东西(马铃薯的定义中没有终身参数)。因此,您将能够将任何关闭传递给give_callback
必须具有'static
lifeTime(这意味着它不借任何东西,除了可能是整个程序长度的生活)。这就是您的编译器错误所表达的内容(游乐场)
编译器正在阻止您这样做:
从广义上讲,您有两个选择。
首先是用终身参数定义
马铃薯
,但这会随着终生参数与马铃薯类型绑定而迅速变得凌乱,并且几乎可以使每种用途的用途复杂化potagy>马铃薯
曾经。第二个(可能是最好的)选项是使您的关闭具有
'静态
寿命。例如,可以通过将您的人存储在arc&lt; person&gt;
中来完成。然后,您使用移动
封闭来创建一个拥有arc&lt; person&gt;
的关闭,以便person
才能删除直到删除关闭之前。例如P.S.我强烈建议您使用
Rustfmt
格式化您的代码(理想情况下,每个保存)。它会让您更快地编写它,并将帮助人们阅读它。The design you posted cannot work. In
ThingUser::get_thing
it takes&mut self
, which means thatself
is a borrow of type&mut dyn ThingUser
. The closure|| { self.make_sandwhich() }
must also borrowself
(although it only needs a non-mut
&dyn ThingUser
to callmake_sandwhich
). That borrow ofself
must live as long as the closure lives.However, you want to store the closure inside a
Potato
. This would mean that after storing it thePotato
is also borrowing&ThingUser
, butPotato
is not defined to borrow anything at all (there are no lifetime parameters in the definition of potato). Therefore any closure you will ever be able to pass togive_callback
must have a'static
lifetime (meaning that it doesn't borrow anything, except possibly things that live for the entire length of the program).This is what's being expressed by your compiler error (playground)
The compiler is stopping you from doing this:
Broadly you have two options.
First would be to define
Potato
with a lifetime parameter, but this will get messy quickly as the lifetime parameter will by tied to the potato type and will complicate pretty much every use ofPotato
ever.The second (probably preferable) option is to make your closure have a
'static
lifetime. This could be done by storing your person in anArc<Person>
, for example. Then you use amove
closure to create a closure which owns anArc<Person>
, so thatPerson
cannot be dropped until the closure is dropped. For exampleP.S. I highly recommend you use
rustfmt
to format your code (ideally on every save). It will make you faster writing it and will help people read it.