gpt4 book ai didi

rust - 如何调用在盒装特征对象上消耗 self 的方法?

转载 作者:行者123 更新时间:2023-11-29 08:20:18 24 4
gpt4 key购买 nike

我有以下实现草图:

trait Listener {
fn some_action(&mut self);
fn commit(self);
}

struct FooListener {}

impl Listener for FooListener {
fn some_action(&mut self) {
println!("{:?}", "Action!!");
}

fn commit(self) {
println!("{:?}", "Commit");
}
}

struct Transaction {
listeners: Vec<Box<dyn Listener>>,
}

impl Transaction {
fn commit(self) {
// How would I consume the listeners and call commit() on each of them?
}
}

fn listener() {
let transaction = Transaction {
listeners: vec![Box::new(FooListener {})],
};
transaction.commit();
}

我可以有 Transaction上面有监听器,当事务发生某些事情时,监听器会调用监听器。自 Listener是一个特征,我存储一个 Vec<Box<Listener>> .

我很难实现 commit对于 Transaction .不知何故,我必须通过调用 commit 来消耗这些盒子在每个存储的 Listener 上s,但据我所知,我不能把东西从盒子里拿出来。

我将如何在提交时使用我的听众?

最佳答案

正在申请 commit到装箱对象是不允许的,因为特征对象不知道它的大小(并且它在编译时不是常量)。由于您计划将监听器用作盒装对象,因此您可以做的是确认 commit将在框上调用并相应地更改其签名:

trait Listener {
fn some_action(&mut self);
fn commit(self: Box<Self>);
}

struct FooListener {}

impl Listener for FooListener {
fn some_action(&mut self) {
println!("{:?}", "Action!!");
}

fn commit(self: Box<Self>) {
println!("{:?}", "Commit");
}
}

这会启用 Transaction按照你编写的方式进行编译,因为在 FooListener 的实现中Self 的大小众所周知,完全有可能将对象移出盒子并同时消耗两者。

此解决方案的价格是 Listener::commit现在需要 Box .如果这 Not Acceptable ,您可以同时声明 commit(self)commit_boxed(self: Box<Self>)在特性中,要求所有类型都实现两者,可能使用私有(private)函数或宏来避免代码重复。这不是很优雅,但它可以同时满足装箱和未装箱的用例,而不会损失性能。

关于rust - 如何调用在盒装特征对象上消耗 self 的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54018162/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com