一起定义 fmt::Display 和 fmt::Debug
Define fmt::Display and fmt::Debug together
是否可以一起定义 fmt::Display
和 fmt::Debug
,即它们使用相同的实现?
假设我们有以下示例代码(仅用于演示目的):
use std::fmt;
struct MyDate {
pub year: u16,
pub month: u8,
pub day: u8
}
impl PartialEq for MyDate {
fn eq(&self, other: &Self) -> bool {
self.year == other.year && self.month == other.month && self.day == other.day
}
}
impl fmt::Display for MyDate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}-{:02}-{:02}", self.year, self.month, self.day)
}
}
impl fmt::Debug for MyDate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
fn main() {
let d1 = MyDate { year: 2008, month: 9, day: 10 };
let d2 = MyDate { year: 2008, month: 9, day: 10 };
println!("Date = {}", d1); // requires fmt::Display
assert_eq!(d1, d2); // requires fmt::Debug
}
似乎为了使用 println
打印我的 class 并使用 assert_eq
编写单元测试,我需要定义两个 fmt
特征。有没有办法让 1 个“打印”实现同时定义 fmt::Display
和 fmt::Debug
?例如,类似于 impl fmt::Debug, fmt::Display for MyDate { ... }
或类似的东西?
或者只是将 #[derive(Debug)]
放在任何 class 前面是常见的做法吗?如果我的问题很天真,我很抱歉,因为我是生锈的新手。
在大多数情况下,Display
和 Debug
有不同的输出。如果在两种情况下都使用相同的格式是有意义的,那么您编写的代码就可以了。 #[derive(Debug)]
也可以——这是你的决定。我认为要记住的重要一点是 Debug
应该 不遗漏任何东西,并且要明确。
在您显示的情况下,Display
格式完全准确地显示了结构的所有字段,因此重用 Display
来实现 Debug
完全没问题。如果你有很多这样的类型,你可以使用一个简单的宏来生成转发到 Display
.
的 Debug
实现
顺便说一句,我建议使用 #[derive(PartialEq)]
而不是您展示的手动 PartialEq 实现。它是完全等价的,并且避免了忘记比较新添加字段的危险失败模式。
是否可以一起定义 fmt::Display
和 fmt::Debug
,即它们使用相同的实现?
假设我们有以下示例代码(仅用于演示目的):
use std::fmt;
struct MyDate {
pub year: u16,
pub month: u8,
pub day: u8
}
impl PartialEq for MyDate {
fn eq(&self, other: &Self) -> bool {
self.year == other.year && self.month == other.month && self.day == other.day
}
}
impl fmt::Display for MyDate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}-{:02}-{:02}", self.year, self.month, self.day)
}
}
impl fmt::Debug for MyDate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
fn main() {
let d1 = MyDate { year: 2008, month: 9, day: 10 };
let d2 = MyDate { year: 2008, month: 9, day: 10 };
println!("Date = {}", d1); // requires fmt::Display
assert_eq!(d1, d2); // requires fmt::Debug
}
似乎为了使用 println
打印我的 class 并使用 assert_eq
编写单元测试,我需要定义两个 fmt
特征。有没有办法让 1 个“打印”实现同时定义 fmt::Display
和 fmt::Debug
?例如,类似于 impl fmt::Debug, fmt::Display for MyDate { ... }
或类似的东西?
或者只是将 #[derive(Debug)]
放在任何 class 前面是常见的做法吗?如果我的问题很天真,我很抱歉,因为我是生锈的新手。
在大多数情况下,Display
和 Debug
有不同的输出。如果在两种情况下都使用相同的格式是有意义的,那么您编写的代码就可以了。 #[derive(Debug)]
也可以——这是你的决定。我认为要记住的重要一点是 Debug
应该 不遗漏任何东西,并且要明确。
在您显示的情况下,Display
格式完全准确地显示了结构的所有字段,因此重用 Display
来实现 Debug
完全没问题。如果你有很多这样的类型,你可以使用一个简单的宏来生成转发到 Display
.
Debug
实现
顺便说一句,我建议使用 #[derive(PartialEq)]
而不是您展示的手动 PartialEq 实现。它是完全等价的,并且避免了忘记比较新添加字段的危险失败模式。