Совместное использование слабых признаков объекта
Я пытаюсь предоставить "взгляды" на не принадлежащие ему структуры для разделения компонентов системы.
Предположим, набор черт с различными методами: 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
).
- Есть ли способ сделать это?
- Это правильный путь для достижения этого?
- Есть ли более идиоматический способ реализации этой функциональности?
Система содержит несколько черт, поэтому создание единой черты с использованием методов всех других черт кажется плохой идеей. Несколько признаков имеют более одного метода, поэтому заменить их замыканиями невозможно.
Что я пробовал
Как один объект может производить один или несколько Rc<Trait>
мы могли бы представить реализацию этого с HashMap<ID, Vec<Rc<Any>>>
в результате чего каждая структура имеет уникальный ID
, который отображается на список всех Rc
которые были сделаны для этого.
Когда мы хотим удалить объект, мы удаляем его из соответствующего списка и удаляем запись в hashmap, аннулируя все Weak
Рекомендации.
Однако реализовать это не удается, так как вставить в HashMap
нужно подбросить Rc<Trait>
-> Rc<Any>
Только чтобы удручить это позже.
1 ответ
Я не уверен, что это идиоматический способ сделать это, но с тех пор я разработал ящик, обеспечивающий эту функциональность - dependent_view
,
Используя ящик, начальная проблема может быть решена с помощью DependentRc
вместо простого Rc
"S:
struct ObjectManager {
boxes: Vec<DependentRc<Box>>,
panels: Vec<DependentRc<Panel>>,
expressions: Vec<DependentRc<Expression>>
}
let object_manager : ObjectManager = ObjectManager::new();
Затем с помощью макросов, предоставленных ящиком, мы можем получить 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<>
ссылки, которые были сделаны из него.