我如何为另一个trait派生trait?

12
我有一个结构体,其中包含一个特质对象成员,就像这样:
trait Contract {}

#[derive(Debug)]
struct Foo {
    x: Box<dyn Contract>,
}

我想让那个结构体派生 Debug,但编译器不喜欢它:

error[E0277]: `Contract + 'static` doesn't implement `std::fmt::Debug`
 --> src/main.rs:5:5
  |
5 |     x: Box<Contract>,
  |     ^^^^^^^^^^^^^^^^ `Contract + 'static` cannot be formatted using `:?`; add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
  |
  = help: the trait `std::fmt::Debug` is not implemented for `Contract + 'static`
  = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::boxed::Box<Contract + 'static>`
  = note: required because of the requirements on the impl of `std::fmt::Debug` for `&std::boxed::Box<Contract + 'static>`
  = note: required for the cast to the object type `std::fmt::Debug`

我真的不确定如何解决这个问题。我理解为什么编译器无法实现Debug trait,因为它不能确定哪些类型会实现它,但正是出于同样的原因,让我无法手动为trait实现它(甚至不确定是否可能)。
要获得我想要的行为,应该采用什么方法?
2个回答

20
特性无法使用#[derive()]属性;您需要手动实现它:
trait Contract {}

impl std::fmt::Debug for dyn Contract {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", "derp")
    }
}

由于特质对象会丢失类型信息(type erasure),您可以利用Contract实现的函数,但是您将无法访问底层类型或其对Debug的具体实现。

然而,如果您使Contract依赖于Debug特质,确保所有实现者都必须实现Debug

trait Contract: std::fmt::Debug {}

您将能够为foo使用#[derive(Debug)],无需手动为Contract实现Debug


太好了,这正是我在寻找的Rust语法。非常感谢! - Dash83

-2
根据 Rust 2021,您可以像这样为另一个 trait 实现 trait:
trait Contract: Debug {}

#[derive(Debug)]
struct Foo {
    x: Box<Contract>,
}

这已经在现有答案中涵盖了(这对于 Rust 2021 并不是新的)。 - Chayim Friedman

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