简体   繁体   English

如何引用特征并仍然使用原始结构?

[英]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.

相关问题 何时使用引用或框包含在结构中实现特征的字段? - When to use a reference or a box to have a field that implements a trait in a struct? 我如何在结构中有一个特征字段? - How do I have a trait field in a struct? 如何为结构体的引用实现 Add trait? - How do I implement the Add trait for a reference to a struct? 一个结构是否可以引用具有泛型方法的trait对象,而不使该结构本身具有泛型? - Is it possible for a struct to have a reference to a trait object that has generic methods, without making the struct itself generic? 如何从盒装特征 object 中获取对结构的引用? - How to get reference to struct from boxed trait object? 如何让一个特征方法有一个结构参数,其中一个项目必须实现相同的特征? - How to have a trait method have a struct argument, in which an item must implement that same trait? 移动结构后,我对结构成员的引用如何仍然有效? - How is my reference to a struct member still valid after the struct was moved? 定义结构时如何使用特征中的常量? - How to use a constant from a trait when defining a struct? 当特征和结构使用相同的方法名称时,如何调用方法? - How to call a method when a trait and struct use the same method name? 我如何使用 @ 字符作为 Rust 装饰器来实现结构的特征? - how could i use @ character as a Rust decorator to implement trait to a struct?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM