如何在Rust中链式调用多个`into()`函数?

4
在我的 Rust 项目中,我有一个多层级的枚举层次结构。这是一个简化版(playground link):
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)
    }
}

如果我想从一个Child转换成一个Parent,现在可以这样做。
let c: Child = Child::ChildA;
let p: Parent = c.into();

但是,如果我想从一个Child转换为一个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 Parentimpl AsRef<Parent> for Child 有何看法? - MeetTitan
对于这个应用程序,我确实想要使用 Child 结构体(这种转换通常是在最后一次使用 Child 结构体时进行),但 AsRef 也是一个有价值的工具。 - Greg Owen
2个回答

5
let c: Child = Child::ChildA;
let gp: GrandParent = Into::<Parent>::into(c).into();

0

如果你只是想让它编译通过,可以使用 Into::<TypeToConvertTo>::into(src),但我建议你仔细考虑一下问题,是否真的需要链式调用 into()(提示:很可能不需要)


你能否提供更多关于为什么我“很可能”不想这样做的信息? - Greg Owen
@greg 因为这样你就无法在原始数据上调用任何方法了。我假设子类和父类有不同的行为,借用其他行为可能比放弃其中一个行为更好。当然,这取决于你的代码结构如何。 - MeetTitan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接