首页 > 解决方案 > 共享弱特征对象引用

问题描述

我试图提供非拥有结构的“视图”来分离系统的组件。

假设一组具有不同方法的特征:DrawableModifiable以及许多实现至少一个特征的结构 - SimpleBoxPanelExpression

系统的不同组件将需要使用特定特征的方法频繁访问这些对象的序列;考虑 aDrawingManager或 a 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)。

该系统包含多个特征,因此使用所有其他特征的方法制作单个特征似乎是个坏主意。几个特征有不止一种方法,所以用闭包替换它们是不可能的。

我试过的

由于一个对象可能产生一个或多个Rc<Trait>,我们可以设想通过HashMap<ID, Vec<Rc<Any>>>使每个结构都有一个唯一的 来实现这一点ID,它映射到Rc为它制作的所有内容的列表。

当我们想要删除一个对象时,我们将它从相应的列表中删除,并删除 hashmap 中的条目,使所有Weak引用无效。

但是,实现这一点失败了,因为要插入HashMap,必须向上转换Rc<Trait>-> Rc<Any>,然后才能向下转换它。

标签: rusttraitstrait-objects

解决方案


我不确定这是否是这样做的惯用方式,但我已经开发了一个提供此功能的板条箱 - dependent_view.

使用板条箱,最初的问题可以通过使用DependentRc而不是普通Rc的来解决:

struct ObjectManager {
    boxes: Vec<DependentRc<Box>>,
    panels: Vec<DependentRc<Panel>>,
    expressions: Vec<DependentRc<Expression>>
}

let object_manager : ObjectManager = ObjectManager::new();

然后使用 crate 提供的宏,我们可以获得Weak<>对这些结构的引用:

let box_view : Weak<Drawable> = to_view!(object_manager.boxes[0]);
let panel_view : Weak<Drawable> = to_view!(object_manager.panels[0]);
let expression_view : Weak<Drawable> = to_view!(object_manager.expressions[0]);

有了这个,删除相应的DependentRc<>将使所有Weak<>对它的引用都无效。


推荐阅读