Methods 构建器是否可以使用所创建对象的方法注册回调?

Methods 构建器是否可以使用所创建对象的方法注册回调?,methods,callback,closures,rust,builder,Methods,Callback,Closures,Rust,Builder,给定:对象Foo和FooBuilder。FooBuilder必须创建对象,并使用所创建对象的方法注册回调。在这种情况下,生成器充当对象Foo的高级自定义,该对象需要根据收到的事件进行更改。静态方法不是强制性的,但仍然是可取的。main()的末尾是事件循环 #[macro_use] extern crate lazy_static; use std::sync::Mutex; struct Global { callbacks: Vec<Box<Fn(i32) + 'st

给定:对象
Foo
FooBuilder
FooBuilder
必须创建对象,并使用所创建对象的方法注册回调。在这种情况下,生成器充当对象
Foo
的高级自定义,该对象需要根据收到的事件进行更改。静态方法不是强制性的,但仍然是可取的。main()的末尾是事件循环

 #[macro_use]
extern crate lazy_static;

use std::sync::Mutex;

struct Global {
    callbacks: Vec<Box<Fn(i32) + 'static + Send + Sync>>
}

lazy_static! {
    static ref GLOBAL: Mutex<Global> = {
        Mutex::new(Global {
            callbacks: Vec::new()
        })
    };
}

struct FooBuilder {
    c: i32
}
impl FooBuilder {
    fn new() -> FooBuilder {
        FooBuilder {
            c: 0
        }
    }
    fn build(&self) -> Foo {
        let foo = Foo {
            f: self.c
        };
        // foo.set_callback(|x| foo.edit());
        // ^ ERROR
        foo
    }
}
struct Foo {
    f: i32
}
impl Foo {
    fn edit(&mut self) {
        self.f += 1;
        println!("{:?}", self.f);
    }
    fn set_callback<F>(&self, f: F)
        where F: Fn(i32)  + 'static + Send + Sync {
        GLOBAL.lock().unwrap().callbacks.push(Box::new(f));
    }
}

fn main() {
    let foo = FooBuilder::new().build();
    /* event loop */
}
#[宏使用]
外部板条箱(静态);
使用std::sync::Mutex;
结构全局{
回调:Vec不适用于您的情况

考虑代码的这一部分:

fn set_callback<F>(&self, f: F)
    where F: Fn(i32) + 'static + Send + Sync

从您编辑的评论中:

那么这种方法就不太合适了

问题在于,您对问题建模的方式充满了危险,铁锈正在阻止您自食其果。您只能拥有一个对项的可变引用。除此之外,您还试图在函数调用之间共享对堆栈分配项的引用

也许您会更乐意使用一种更接近垃圾收集语言可能创建的解决方案

在这里,我们使用允许多个线程共享单个可变项。我们使用,以便多个线程可以共享该项的所有权

我还将
set\u callback
移动到了一个自由函数,因为它与您之前启用的结构没有关系

调用
set\u callback
时,我们克隆了增加引用计数的
Arc
,并将该克隆提供给全局队列。由于
Mutex
具有内部可变性,因此函数可以保持
Fn

#[macro_use]
extern crate lazy_static;

use std::sync::{Mutex,Arc};

struct Global {
    callbacks: Vec<Box<Fn(i32) + 'static + Send + Sync>>
}

fn set_callback<F>(f: F)
    where F: Fn(i32) + 'static + Send + Sync
{
    GLOBAL.lock().unwrap().callbacks.push(Box::new(f));
}

lazy_static! {
    static ref GLOBAL: Mutex<Global> = {
        Mutex::new(Global {
            callbacks: Vec::new()
        })
    };
}

struct FooBuilder;

impl FooBuilder {
    fn build(&self) -> Arc<Mutex<Foo>> {
        let foo = Arc::new(Mutex::new(Foo));
        let inner_foo = foo.clone();
        set_callback(move |_| inner_foo.lock().unwrap().edit());
        foo
    }
}

struct Foo;

impl Foo {
    fn edit(&mut self) {}
}

fn main() {
    let _foo = FooBuilder.build();
}
#[宏使用]
外部板条箱(静态);
使用std::sync::{Mutex,Arc};
结构全局{
回调:Vec Arc{
设foo=Arc::new(Mutex::new(foo));
让internal_foo=foo.clone();
设置回调(移动| |内部| foo.lock().unwrap().edit());
福
}
}
结构Foo;
impl-Foo{
fn编辑(&mut self){}
}
fn main(){
让_foo=FooBuilder.build();
}
不适用于您的情况

考虑代码的这一部分:

fn set_callback<F>(&self, f: F)
    where F: Fn(i32) + 'static + Send + Sync

从您编辑的评论中:

那么这种方法就不太合适了

问题在于,您对问题建模的方式充满了危险,铁锈正在阻止您自食其果。您只能拥有一个对项的可变引用。除此之外,您还试图在函数调用之间共享对堆栈分配项的引用

也许您会更乐意使用一种更接近垃圾收集语言可能创建的解决方案

在这里,我们使用允许多个线程共享单个可变项。我们使用,以便多个线程可以共享该项的所有权

我还将
set\u callback
移动到了一个自由函数,因为它与您之前启用的结构没有关系

调用
set\u callback
时,我们克隆了增加引用计数的
Arc
,并将该克隆提供给全局队列。由于
Mutex
具有内部可变性,因此函数可以保持
Fn

#[macro_use]
extern crate lazy_static;

use std::sync::{Mutex,Arc};

struct Global {
    callbacks: Vec<Box<Fn(i32) + 'static + Send + Sync>>
}

fn set_callback<F>(f: F)
    where F: Fn(i32) + 'static + Send + Sync
{
    GLOBAL.lock().unwrap().callbacks.push(Box::new(f));
}

lazy_static! {
    static ref GLOBAL: Mutex<Global> = {
        Mutex::new(Global {
            callbacks: Vec::new()
        })
    };
}

struct FooBuilder;

impl FooBuilder {
    fn build(&self) -> Arc<Mutex<Foo>> {
        let foo = Arc::new(Mutex::new(Foo));
        let inner_foo = foo.clone();
        set_callback(move |_| inner_foo.lock().unwrap().edit());
        foo
    }
}

struct Foo;

impl Foo {
    fn edit(&mut self) {}
}

fn main() {
    let _foo = FooBuilder.build();
}
#[宏使用]
外部板条箱(静态);
使用std::sync::{Mutex,Arc};
结构全局{
回调:Vec Arc{
设foo=Arc::new(Mutex::new(foo));
让internal_foo=foo.clone();
设置回调(移动| |内部| foo.lock().unwrap().edit());
福
}
}
结构Foo;
impl-Foo{
fn编辑(&mut self){}
}
fn main(){
让_foo=FooBuilder.build();
}

请在你的问题中添加准确的错误信息。你应该进一步最小化你的示例,只要它不改变错误信息(例如用{a,b}
删除
)。请在你的问题中添加准确的错误信息。你应该进一步最小化你的示例,只要它不改变错误信息(例如,{ A,B } /代码>),如果我们考虑回调作为外部API的注册,有可能使它更漂亮吗?如果我们考虑回调作为外部API的注册,有可能使它更漂亮吗?