#rust
#Ржавчина
Вопрос:
В одном из моих проектов Rust у меня есть многоуровневая иерархия перечислений. Вот упрощенная версия (ссылка на игровую площадку):
enum Child {
ChildA,
ChildB,
}
enum Parent {
ParentA(Child),
ParentB,
}
enum GrandParent {
GrandParentA(Parent),
GrandParentB,
}
Для удобства я реализовал конвертеры между каждым уровнем и уровнем выше него:
impl From<Child> for Parent {
fn from(c: Child) -> Self {
Parent::ParentA(c)
}
}
impl From<Parent> for GrandParent {
fn from(p: Parent) -> Self {
GrandParent::GrandParentA(p)
}
}
Если я хочу преобразовать из a Child
в a Parent
, теперь я могу сделать
let c: Child = Child::ChildA;
let p: Parent = c.into();
Но если я хочу преобразовать из a Child
в a Grandparent
, я, похоже, не могу связать несколько вызовов с into()
:
let c: Child = Child::ChildA;
let gp: GrandParent = c.into().into();
error[E0282]: type annotations needed
--> src/main.rs:30:29
|
30 | let gp: GrandParent = c.into().into();
| --^^^^--
| | |
| | cannot infer type for type parameter `T` declared on the trait `Into`
| this method call resolves to `T`
|
= note: type must be known at this point
Я попытался указать тип с помощью turbofish, но это тоже не работает:
let c = Child::ChildA;
let gp: GrandParent = c.into::<Parent>().into();
error[E0107]: wrong number of type arguments: expected 0, found 1
--> src/main.rs:31:36
|
31 | let gp: GrandParent = c.into::<Parent>().into();
| ^^^^^^ unexpected type argument
Каков правильный способ связать эти вызовы into()
?
Комментарии:
1. При преобразовании вы используете исходную структуру (что может быть тем, что вы хотите, но я предполагаю, что у вас есть определенные методы для каждого). Как вы относитесь к
impl AsRef<Child> for Parent
andimpl AsRef<Parent> for Child
?2. Для этого приложения я хочу использовать
Child
структуру (это преобразование всегда используется в последний разChild
, когда используется структура), ноAsRef
это также ценный инструмент.
Ответ №1:
let c: Child = Child::ChildA;
let gp: GrandParent = Into::<Parent>::into(c).into();
Ответ №2:
Если вы просто хотите, чтобы это скомпилировалось, используйте Into::<TypeToConvertTo>::into(src)
, но я бы посоветовал изучить проблему и выяснить, действительно ли связанные вызовы into()
— это то, что вы хотите (подсказка: скорее всего, это не так)
Комментарии:
1. Не могли бы вы дать больше информации о том, почему я «скорее всего» не хотел бы этого делать?
2. @greg потому что тогда вы не сможете вызывать какие-либо методы для своих исходных данных. Я предполагаю, что дочерние и родительские элементы имеют разное поведение, и потенциально было бы лучше позаимствовать поведение других, а не отбрасывать одно поведение для другого. Это, очевидно, зависит от того, как структурирована остальная часть вашего кода.