Rust 如何调用在装箱的trait对象上使用self的方法?
我有一个实现的草图:Rust 如何调用在装箱的trait对象上使用self的方法?,rust,ownership-semantics,Rust,Ownership Semantics,我有一个实现的草图: 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) {
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<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();
}
trait侦听器{
fn一些动作(多个自我);
fn承诺(自我);
}
结构愚笨者{}
傻瓜监听器的impl监听器{
fn某些操作(&mut self){
println!(“{:?}”,“Action!!”;
}
fn提交(自我){
println!(“{:?}”,“提交”);
}
}
结构事务{
听众:Vec,,
}
impl事务{
fn提交(自我){
//如何使用侦听器并对每个侦听器调用commit()?
}
}
fn侦听器(){
让交易=交易{
监听器:vec![Box::new(傻瓜监听器{}],
};
commit();
}
我可以让Transaction
s上有监听器,当该事务发生某些事情时,这些监听器将调用监听器。因为Listener
是一种特性,所以我存储了一个Vec
对于事务
,我很难实现提交
。不知何故,我必须通过调用每个存储的侦听器上的commit
来消耗盒子,但据我所知,我无法将东西移出盒子
提交时如何使用侦听器?不允许将commit
应用于已装箱的对象,因为trait对象不知道其大小(并且在编译时它不是常量)。由于您计划将侦听器用作装箱对象,因此您可以做的是确认将在箱子上调用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");
}
}
trait侦听器{
fn一些动作(多个自我);
fn提交(self:Box);
}
结构愚笨者{}
傻瓜监听器的impl监听器{
fn某些操作(&mut self){
println!(“{:?}”,“Action!!”;
}
fn提交(self:Box){
println!(“{:?}”,“提交”);
}
}
这使Transaction
能够在编写时进行编译,因为在woulListener
的实现中,Self
的大小是众所周知的,完全可以将对象移出框中并同时使用这两个对象
此解决方案的价格是,Listener::commit
现在需要一个框
。如果这是不可接受的,您可以在trait中声明commit(self)
和commit\u boxed(self:Box)
,要求所有类型都实现这两个功能,可能使用私有函数或宏来避免代码重复。这不是很优雅,但它可以在不损失性能的情况下满足装箱和未装箱的用例。启用此功能后,自然代码:
把“东西”从盒子里拿出来很容易。您的情况更复杂,因为您不再知道存储在盒子中的值有多大。这意味着您将遇到一个错误:无法移动Listener类型的值:无法静态确定Listener的大小。这是否适用于trait对象?比如,如果我有一个letbox:box
,我可以调用box.commit()代码>?我这样问是因为Self
将成为一个愚蠢的听者,而不是听者,对吗?@Lucretiel是的,答案(很可能是这个问题)是在考虑特质对象的情况下写的。
// 1.37.0-nightly 2019-06-03 6ffb8f53ee1cb0903f9d
#![feature(unsized_locals)]
// ...
impl Transaction {
fn commit(self) {
for l in self.listeners {
l.commit()
}
}
}