[英]How to have a reference to a trait and still use original struct?
My goal is to have a reference counted struct which is referred as a trait in one context and by its concrete type in another. 我的目标是有一个引用计数结构,它在一个上下文中被称为特征,在另一个上下文中被称为特定类型。 Best explained in code:
最佳代码解释:
#![feature(box_syntax)]
use std::rc::Rc;
use std::cell::RefCell;
trait Employee {
fn be_managed(&mut self);
}
struct Human;
impl Human {
fn be_human(&mut self) {
println!("I'm just a human who needs a mutable self sometimes");
}
}
impl Employee for Human {
fn be_managed(&mut self) {
println!("Off to the salt mines");
}
}
struct Manager {
my_employee: Rc<RefCell<Box<Employee + 'static>>>, //'
}
fn main() {
let mut human1 = Rc::new(RefCell::new(box Human as Box<Employee>));
let manager1 = Manager {
my_employee: human1.clone(), // This works due to cast above
};
manager1.my_employee.borrow_mut().be_managed();
human1.borrow_mut().be_human(); // But we can't be human anymore
let mut human2 = Rc::new(RefCell::new(box Human));
let manager2 = Manager {
my_employee: human2.clone(), // This doesn't work
};
manager2.my_employee.borrow_mut().be_managed();
human2.borrow_mut().be_human();
}
I want the Manager
to be able to have any struct implementing the Employee
trait as my_employee
, but other references should still be able to call other methods on the original object, ie be_human
. 我希望
Manager
能够将任何实现Employee
特征的结构体作为my_employee
,但是其他引用仍然可以调用原始对象上的其他方法,即be_human
。
Right now I'm getting the following errors from the above code: 现在我从上面的代码中得到以下错误:
src/main.rs:37:25: 37:35 error: type `core::cell::RefMut<'_, Box<Employee>>` does not implement any method in scope named `be_human`
src/main.rs:37 human1.borrow_mut().be_human(); // But we can't be human anymore
^~~~~~~~~~
src/main.rs:44:22: 44:36 error: mismatched types:
expected `alloc::rc::Rc<core::cell::RefCell<Box<Employee + 'static>>>`,
found `alloc::rc::Rc<core::cell::RefCell<Box<Human>>>`
(expected trait Employee,
found struct `Human`) [E0308]
src/main.rs:44 my_employee: human2.clone(), // This doesn't work
^~~~~~~~~~~~~~
What's the right approach in this situation? 在这种情况下,正确的方法是什么?
Disclaimer: in this answer I will assume that you are willingly NOT using an enum
because you want Employee
to be open. 免责声明:在这个答案中,我会假设您不愿意使用
enum
因为您希望Employee
开放。
This issue comes up in about every single language that uses dynamic polymorphism, and the traditional answer is the Visitor Pattern . 这个问题出现在使用动态多态的每种语言中,传统的答案是访问者模式 。
It is not exactly ideal, though, because of the dependencies it introduces, so if necessary you can use the Acyclic Visitor Pattern ; 但是,由于它引入了依赖性,它并不完全理想,因此如果需要,您可以使用非循环访问者模式 ; however I advise that you start with a bare bone visitor before delving further.
但是我建议你先从裸骨访客开始,然后再深入研究。
trait EmployeeVisitor {
fn visit_employee(&self, e: &Employee);
fn visit_human(&self, h: &Human);
}
trait Employee {
fn accept(&self, v: &EmployeeVisitor) {
v.visit_employee(self);
}
}
impl Employee for Human {
fn accept(&self, v: &EmployeeVisitor) {
v.visit_human(self);
}
}
This is the traditional "every problem can be solved with a layer of indirection", and it incurs the traditional issue of bringing another layer of indirection. 这是传统的“每个问题都可以用一层间接来解决”,它带来了传统的另一层间接问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.