【发布时间】:2019-01-08 07:27:01
【问题描述】:
我正在尝试提供非拥有结构的“视图”来分离系统的组件。
假设一组具有不同方法的特征:Drawable、Modifiable 和许多实现至少一个特征的结构 - SimpleBox、Panel、Expression。
系统的不同组件需要频繁访问这些对象的序列,使用特定特征的方法;考虑DrawingManager 或ModifyManager:
struct DrawingManager {
items: Vec<Weak<Drawable>>,
}
struct ModifyManager {
items: Vec<Weak<Modifiable>>
}
虽然可以在两个管理器中引用单个对象,但假设所有结构都有一个单独的所有者:
struct ObjectManager {
boxes: Vec<Rc<Box>>,
panels: Vec<Rc<Panel>>,
expressions: Vec<Rc<Expression>>,
}
理想情况下,能够管理从一个位置删除结构会很有用 - 即只需将其从 ObjectManager 中删除就足以使所有其他组件中的引用无效(因此使用 Weak)。
- 有没有办法做到这一点?
- 这是实现此目的的正确方法吗?
- 是否有更惯用的方式来实现此功能?
该系统包含多个特征,因此使用所有其他特征的方法制作单个特征似乎是个坏主意。几个 trait 有不止一种方法,所以用闭包替换它们是不可能的。
我的尝试
由于一个对象可能产生一个或多个Rc<Trait>,我们可以设想用HashMap<ID, Vec<Rc<Any>>> 来实现这一点,从而我们使每个结构都有一个唯一的ID,它映射到所有Rc 的列表为它而生。
当我们想要移除一个对象时,我们将它从对应的列表中移除,并移除hashmap中的条目,使所有Weak引用失效。
但是,执行此操作失败,因为要插入HashMap,必须向上转换Rc<Trait> -> Rc<Any>,稍后才能向下转换。
【问题讨论】:
-
有没有办法做到这一点? 和 这是实现这一目标的正确方法吗? 有点矛盾。您拥有的解决方案是否符合您的要求?如果不是,那有什么问题?
-
对不起,我的措辞不清楚。我没有编译解决方案。
-
虽然您可以通过克隆转换一个
Rc<struct> -> Rc<Trait>,然后使用Rc::downgrade将对该Weak<Trait>的引用转换为Weak<Trait>,但我还没有找到一种合适的方法来首先存储@987654345 @ 转换为超类型的序列(例如Vec<Rc<Any>>,然后将对超类型的引用向下转换为对原始类型的引用(&Rc<Any> -> &Rc<Trait>)。 -
这个问题的主要要点不是向下转换 - 而是获得 Weak
引用 - 这提供了两个重要功能 - 维护数据的单个“所有者”,同时还允许处理多个引用相同的 - 即持有 vec<Weak<Trait>>的序列,而不是每个独立类型的多个列表。碰巧在我的示例中,我遇到了向下转换的问题(但只是因为我之前立即向上转换)。
标签: rust traits trait-objects