В проекте, над которым я работаю, есть этот объект:
enum ContainedType {
SomeType,
OtherType,
...
}
struct OurObject {
contains: ContainedType,
...
}
impl OurObject {
pub fn unpack_sometype(self) -> AType { ... }
pub fn unpack_othertype(self) -> BType { ... }
...
}
OurObject
- это контейнер вещей, которые каким-то образом «упакованы».Каждая вещь, которая может быть упакована, реализует различные черты.
Мы заканчиваем повторяющимся кодом вроде:
match foo.type() {
SomeType => action(foo.unpack_sometype()),
OtherType => action(foo.unpack_othertype()),
...
}
Я хотел бы выделить код match
в функцию, чтобы мы могли отправитьна произвольную черту.
action(foo)
Однако я сталкиваюсь с проблемами ...
pub fn dispatch<T>(obj: OurObject) -> Box<T> {
match obj.type() {
SomeType => Box::new(obj.unpack_sometype()),
OtherType => Box::new(obj.unpack_othertype()),
...
}
}
T
здесь предполагается заменить произвольную черту, такую как Debug
или SomeLocalTrait
.
Я также пытался использовать турбовину, как Box::<T>::new()
, но безрезультатно.Компилятор жалуется, что T
не говорит компилятору, что это только черта.Есть ?Sized
, но я не могу найти ?IAmTrait
.Новый синтаксис Rust 2018 impl Trait
не работает аналогичным образом.
Пока что я обошел это, создав функции с помощью макроса.Итак, у меня есть dispatch_debug
или dispatch_cool_trait
.По существу, повторная реализация универсального интерфейса.Поскольку мы хотим использовать это для несвязанных черт, я не могу использовать некоторую форму родительской черты.Debug
или Display
не связаны с какой-либо чертой, которую мы создали бы.
Есть ли лучший способ?В идеальном мире у нас была бы dispatch
функция или метод, который позволил бы нам сказать:
action(foo.dispatch<SomeTrait>())
Это песочница, показывающая упрощенную версию для начала разговора.https://play.rust -lang.org /? Версия = стабильные и режим = отлаживать и издание = 2018 & сути = 7b739ab11da15ec793ee46c2d8ac47fc