如何提供默认的 Debug 实现?
How do I provide a default Debug implementation?
对于您创建的大多数有助于调试的结构,#[derive(Debug)]
被认为是一种很好的做法。但是,如果您的结构包含不带 Debug
的类型(例如特征),则这是不可能的。但是如果特征在我的控制之下,我可以做些什么来让用户对所述特征的实现显示在调试消息中吗?
我可以要求实现我的特征的人也实现 Debug
,但我不喜欢添加这种任意要求:
trait MyTrait: Debug { ... }
我可以为我的特质实施 Debug
:
trait MyTrait { ... }
impl Debug for MyTrait {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "MyTrait {{ ... }}")
}
}
这不允许实现覆盖 Debug
- 就好像该函数不是虚拟的一样。我怎样才能使这项工作?
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct A {
a: Box<Data>,
}
trait Data {}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data{{ ... }}")
}
}
#[derive(Debug)]
struct B(i32);
impl Data for B {}
fn main() {
let a = A{ a: Box::new(B(42)) };
println!("{:?}", a);
}
输出:
A { a: Data{ ... } }
我想要的:
A { a: B(42) }
我只想要 B
未实现 Debug
时的第一个输出。
您可以创建自己的特征方法。希望增强调试 和 实现 Debug
的类型可以委托:
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct Container(Box<Data>);
trait Data {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data {{ ... }}")
}
}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.debug_fmt(f)
}
}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
self.fmt(f)
}
}
#[derive(Debug)]
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
需要不稳定专业化功能的替代解决方案:
#![feature(specialization)]
use std::fmt;
use std::fmt::{Formatter, Debug};
struct Container<D>(Box<D>) where D: Data;
impl<D> Debug for Container<D>
where D: Data
{
default fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container(Data {{ ... }})")
}
}
impl<D> Debug for Container<D>
where D: Data + Debug
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container({:?})", self.0)
}
}
trait Data {}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {}
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
请注意,这会给容器带来负担。
对于您创建的大多数有助于调试的结构,#[derive(Debug)]
被认为是一种很好的做法。但是,如果您的结构包含不带 Debug
的类型(例如特征),则这是不可能的。但是如果特征在我的控制之下,我可以做些什么来让用户对所述特征的实现显示在调试消息中吗?
我可以要求实现我的特征的人也实现 Debug
,但我不喜欢添加这种任意要求:
trait MyTrait: Debug { ... }
我可以为我的特质实施 Debug
:
trait MyTrait { ... }
impl Debug for MyTrait {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "MyTrait {{ ... }}")
}
}
这不允许实现覆盖 Debug
- 就好像该函数不是虚拟的一样。我怎样才能使这项工作?
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct A {
a: Box<Data>,
}
trait Data {}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data{{ ... }}")
}
}
#[derive(Debug)]
struct B(i32);
impl Data for B {}
fn main() {
let a = A{ a: Box::new(B(42)) };
println!("{:?}", a);
}
输出:
A { a: Data{ ... } }
我想要的:
A { a: B(42) }
我只想要 B
未实现 Debug
时的第一个输出。
您可以创建自己的特征方法。希望增强调试 和 实现 Debug
的类型可以委托:
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct Container(Box<Data>);
trait Data {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data {{ ... }}")
}
}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.debug_fmt(f)
}
}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
self.fmt(f)
}
}
#[derive(Debug)]
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
需要不稳定专业化功能的替代解决方案:
#![feature(specialization)]
use std::fmt;
use std::fmt::{Formatter, Debug};
struct Container<D>(Box<D>) where D: Data;
impl<D> Debug for Container<D>
where D: Data
{
default fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container(Data {{ ... }})")
}
}
impl<D> Debug for Container<D>
where D: Data + Debug
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container({:?})", self.0)
}
}
trait Data {}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {}
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
请注意,这会给容器带来负担。