如何为具有trait对象成员的结构体实现Debug trait?

7
我的目标是打印具有trait object成员的struct的内容,但我找不到告诉Rust编译器该成员还实现了其他trait(如Display或Debug)的方法。
例如,在以下程序中,我想打印S2的结构体(并进行比较的S1),但我在fmt的实现中遇到了困难。
trait Tr {}

impl Tr for usize {}

impl Tr for String {}

#[derive(Debug)]
struct S1<A: Tr + std::fmt::Debug> {
    member: Box<A>,
}

struct S2 {
    member: Box<Tr>,
}

impl std::fmt::Debug for S2 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        // ??
        Ok(())
    }
}

fn main() {
    let s1 = S1 {
        member: Box::new(String::from("abc")),
    };

    println!("{:?}", s1);

    let s2 = S2 {
        member: Box::new(String::from("abc")),
    };

    println!("{:?}", s2);
}

我希望这个程序的输出结果是:

S1 { member: "abc" }
S2 { member: "abc" }

是否有可能为像S2这样的结构体实现Debug

(Rust版本:1.35)


1
“T”不是一个好的trait名称,因为如果我看到“Box<T>”,我会期望“T”是通过结构体提供的泛型类型参数,例如“struct S2<T> {}”。应该使用更长的名称。 - hellow
2个回答

5

是否可以为像S2这样的结构体实现Debug

可以的,并且在Rust官方文档中也明确指出了这一点。

你需要按照以下方式为你的S2实现Debug trait:

trait MyTrait {}
impl MyTrait for usize {}
impl MyTrait for String {}

trait MyTraitWritable: MyTrait + Debug {}
impl MyTraitWritable for usize {}
impl MyTraitWritable for String {}

impl std::fmt::Debug for S2 {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        write!(fmt, "S2 {{ member: {:?} }}", self.member)
    }
}

游乐场


1
通常情况下,只需使用 std::fmt::Result - Shepmaster
@Shepmaster,根据您的评论修改了答案。 - Akiner Alkan
通常情况下,我们会提供一个 MyTraitWritable 的全局实现;类似于 impl<T: MyTrait + Debug> MyTraitWritable for T {}(如链接中所示)。 - Shepmaster

1
你可以使 S2 成为泛型类型,但不需要在那里指定该类型还应实现 Debug。相反,你可以在 impl 中指定它:
struct S2<A: Tr> {
    member: Box<A>,
}

impl<A: Tr + std::fmt::Debug> std::fmt::Debug for S2<A> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        write!(fmt, "S2 {{ member: {:?} }}", self.member)?;
        Ok(())
    }
}

这样,如果实际类型允许,S2 将会实现 Debug

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