显示

fmt::Debug 看起来不太紧凑和简洁,因此自定义输出外观通常是有利的。这可以通过手动实现 fmt::Display 来完成,它使用 {} 打印标记。实现它看起来像这样

#![allow(unused)] fn main() { // Import (via `use`) the `fmt` module to make it available. use std::fmt; // Define a structure for which `fmt::Display` will be implemented. This is // a tuple struct named `Structure` that contains an `i32`. struct Structure(i32); // To use the `{}` marker, the trait `fmt::Display` must be implemented // manually for the type. impl fmt::Display for Structure { // This trait requires `fmt` with this exact signature. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Write strictly the first element into the supplied output // stream: `f`. Returns `fmt::Result` which indicates whether the // operation succeeded or failed. Note that `write!` uses syntax which // is very similar to `println!`. write!(f, "{}", self.0) } } }

fmt::Display 可能比 fmt::Debug 更简洁,但这给 std 库带来了问题。应该如何显示不明确的类型?例如,如果 std 库为所有 Vec<T> 实现单一样式,它应该是什么样式?是以下两种中的哪一种?

  • Vec<path>: /:/etc:/home/username:/bin (以 : 分割)
  • Vec<number>: 1,2,3 (以 , 分割)

不,因为没有适用于所有类型的理想样式,并且 std 库不应该规定一种。fmt::Display 没有为 Vec<T> 或任何其他泛型容器实现。在这种泛型情况下,必须使用 fmt::Debug

但这并不是一个问题,因为对于任何新的泛型的容器类型,都可以实现 fmt::Display

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

因此,fmt::Display 已经实现,但 fmt::Binary 尚未实现,因此无法使用。std::fmt 有许多这样的 traits,每个都需要自己的实现。这在 std::fmt 中有更详细的介绍。

练习

在检查上述示例的输出后,使用 Point2D 结构作为指导,向示例中添加 Complex 结构。以相同方式打印时,输出应为

Display: 3.3 + 7.2i Debug: Complex { real: 3.3, imag: 7.2 }

另请参阅

derive, std::fmt, macros, struct, trait, 和 use