// ===== library code: =====
trait Sate { // Or in C++ imagine this is a class containing only pure virtuals.
fn ready(&mut self, ..);
fn terminate(&mut self, ..);
fn timeout(&mut self, .. );
fn ....; // a few more functions
fn as_any(&mut self) -> &mut Any; // for downcasting in Rust; not necessary in C++
}
states: HashMap<u32, Rc<RefCell<State>>>; // Or in C++ just a map of numbers to shared-ptr of State
fn event_loop_on_some_trigger(trigger_for: u32, trigger: Blah) {
let state = states[trigger_for];
if trigger == for_timeout { state.borrow_mut().timeout(...) }
else if trigger = for_readiness { state.borrow_mut().timeout(...) }
...
}
//==== User Code: ====
struct Type0 { ... }
impl State for Type0 { /* provide concrete impls */ } // In C++ this would be inheritance for Type0
struct Type1 { ... }
impl State for Type1 { /* provide concrete impls */ } // In C++ this would be inheritance for Type1
// ... etc.
Я использовал эту библиотеку, и все работало нормально.Но теперь есть несколько типов, которые должны выполнять какую-то конкретную работу, которая выходит за рамки того, что есть в черте State
выше.Так что я, кажется, постепенно сталкиваюсь с «проблемой выражений» в дизайне.Я не управляю библиотекой, предоставляющей черту и цикл обработки событий, и даже если бы я это сделал, я бы не добавил туда 2 или 3 дополнительных функции, так как это неправильно, поскольку она будет использоваться только для некоторых конкретных типов иэто тоже время от времени.
Кроме того, у меня есть карта в коде пользователя, такая как HashMap<u32, SomeDetail>
, которая соответствует карте в стеке потоков цикла событий выше.Поэтому, если мне нужно выполнить специальную операцию для одного из типов, я могу получить значение u32
для состояния (анализируя SomeDetail
или что-то еще), получить состояние из карты в цикле обработки событий и уменьшить его.к типу для вызова одной из специальных функций.
На данный момент в C ++ я, вероятно, использовал бы static_cast<>
, так как я уверен, что это тип (если только в загрузке идентификаторов нет ошибок)или это распределение, которое было бы логической ошибкой в программе).В Rust я вынужден использовать downcast_mut
(dynamic_cast
в C ++), с которым у меня все в порядке (до сих пор у меня никогда не возникало никаких ошибок во время выполнения, показывая, что логика правильна, и static_cast
былион также был бы доступен в Safe-Rust).
Теперь мой вопрос - я читал, что кастинг - это плохой дизайн и т. д. Поэтому я думал, что я мог бы сделать по-другому здесь.Одной из идей было сохранить слабые (или сильные, если нам все равно) ссылки на карте, которые есть в моем коде пользователя.Таким образом, хотя цикл обработки событий использует карту, он должен запустить некоторую функцию для State
, но я бы использовал свою карту, чтобы получить конкретный тип всякий раз, когда я этого захочу, и вызывать функцию для него.Однако, поскольку мой код находится за пределами потока события цикла, мне пришлось бы добавить Mutex к состояниям, что бесполезно в 99% случаев, так как большую часть времени это вызов события Eventloop и типы, выполняющие то, для чего они кодированы.
- Должен ли я хранить несколько карт (ссылок) на конкретные типы, специальные функции, которые я хочу иногда вызывать и шлепать туда мьютекс?
- Просто в этом случае сделайте dynamic_castи это оправданно?
- Eventloop должен был быть шаблонизирован, чтобы дать пользователю возможность сохранить некоторое состояние в стеке потока Eventloop и иметь дело с ним.В этом случае я бы сохранил несколько своих карт
<u32, ConcreteTypeReferences>
, чтобы я мог публиковать запрос в цикле событий в редких случаях, когда я хочу взаимодействовать с конкретными типами, и они могут продолжать жить без мьютекса или атомарной ссылки-четные объекты (в Rust Rc - это не-атомный ref-smart smart-ptr, я не знаю, есть ли эквивалент в C ++)
Последний вариант, а также частично 1-й требуетУ меня есть доступ к этому коду - это скорее список пожеланий, но я просто хочу знать, что было бы предложением, если бы это было так.В отсутствие этого (2) dynamic_cast
кажется единственным жизнеспособным решением?