Боюсь, что вы нарушаете одно из ограничений для Rust, основанное на его дизайне, и ваше единственное реальное решение - это мутация на месте и написание функции-мутатора или четырех.
Проблема с перечислениями в том, что вам нужно до match
, чтобы иметь возможность что-либо с ними делать. До этого момента Rust знает или делает очень мало выводов о том, что такое структура на самом деле. Дополнительной проблемой является отсутствие какой-либо отражающей способности, позволяющей запрашивать тип и выяснять, есть ли у него поле, и невозможность что-либо делать, кроме как полностью соответствовать всему содержимому.
Честно говоря, самый чистый путь может зависеть от цели ваших мутаций. Являются ли они определенным набором изменений в enum
, основанных на какой-то деловой озабоченности? Если это так, вы можете захотеть заключить вашу логику в расширение признака и использовать ее для инкапсуляции логики.
Рассмотрим, например, очень надуманный пример. Мы создаем приложение, которое должно работать с разными предметами и облагать их налогами. Указанные налоги зависят от типа продуктов, и по какой-то причине все наши продукты представлены вариантами enum
, например:
# [Вывести (отладки)]
enum Item {
Еда {цена: у8, калории: у8},
Технология {цена: у8},
}
trait TaxExt {
fn apply_tax(&mut self);
}
impl TaxExt for Item {
fn apply_tax(&mut self) {
match self {
&mut Item::Food {
ref mut price,
calories: _,
} => {
// Our food costs double, for tax reasons
*price *= 2;
}
&mut Item::Technology { ref mut price } => {
// Technology has a 1 unit tax
*price += 1;
}
}
}
}
fn main() {
let mut obj = Item::Food {
price: 3,
calories: 200,
};
obj.apply_tax();
println!("{:?}", obj);
}
детская площадка
Предполагая, что вы можете разделить свою логику следующим образом, это, вероятно, самый чистый способ структурировать это.