如何打印!一个选项<Box<struct>>?
How to print! an Option<Box<struct>>?
我正在尝试打印 Option<Box<MyStruct>>
,但在尝试实现 Display for Option<Box<MyStruct>>
.
时出现编译错误
use std::fmt;
fn main() {
let maybe_my_struct: Option<Box<MyStruct>> = Some(Box::new(MyStruct{foo:42}));
println!("{}", maybe_my_struct);
}
struct MyStruct {
foo: i32,
}
impl fmt::Display for Option<Box<MyStruct>> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Some(MyStruct) => write!(formatter, "{}", self.foo),
None => write!(formatter, "No struct"),
}
}
}
我得到的错误是:
error: the impl does not reference any types defined in this crate;
only traits defined in the current crate can be implemented for arbitrary types [E0117]
我试过为 Option
类型设置别名,而不是实现 Display for MyOption<Box<MyStruct>>
,但结果相同。我做错了什么?
如您所见,您无法为您未编写的类型实现您未编写的特征。这是所谓的 "coherence" 的一部分,它的存在是为了防止非常奇怪的事情,比如链接到库突然导致程序的不相关部分改变行为。
别名 Option
到 MyOption
都不起作用 或者 因为,正如你所说,它是一个 别名 .也就是说,它只是同一事物的另一个名称,并不是实际的不同类型。
现在,如果您像这样围绕 Option
编写 wrapper:
struct MyOption<T>(Option<T>);
then MyOption
将是一个新的、独特的类型,您可以为其实现特征。当然,您需要编写方法来包装和解包您正在存储的实际 Option
。
...但这完全无关紧要,因为您 也可以 为您的结构派生 Debug
并使用它。
fn main() {
let maybe_my_struct: Option<Box<MyStruct>> = Some(Box::new(MyStruct{foo:42}));
println!("{:?}", Some(maybe_my_struct));
}
#[derive(Debug)]
struct MyStruct {
foo: i32,
}
或者,如果您真的想要 Option<Box<MyStruct>>
组合的自定义显示逻辑,您可以使用标记值(顺便说一下,标准库中的 Path
使用了相同的方法)。像这样:
use std::fmt;
fn main() {
let maybe_my_struct: Option<Box<MyStruct>> = Some(Box::new(MyStruct{foo:42}));
println!("{:?}", maybe_my_struct);
// Instead of displaying directly, display via a custom marker.
println!("{}", maybe_my_struct.display());
println!("{}", None::<Box<MyStruct>>.display());
}
#[derive(Debug)]
struct MyStruct {
foo: i32,
}
// This is the marker we'll use to define our custom Display impl.
struct MmsDisplay<'a>(&'a Option<Box<MyStruct>>);
// This trait lets us extend Option<Box<MyStruct>> with a new method.
trait CustomMmsDisplay {
fn display<'a>(&'a self) -> MmsDisplay<'a>;
}
impl CustomMmsDisplay for Option<Box<MyStruct>> {
fn display<'a>(&'a self) -> MmsDisplay<'a> {
MmsDisplay(self)
}
}
// And here's the display logic.
impl<'a> fmt::Display for MmsDisplay<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Some(ref ms) => write!(formatter, "{}", ms.foo),
None => write!(formatter, "No struct"),
}
}
}
我正在尝试打印 Option<Box<MyStruct>>
,但在尝试实现 Display for Option<Box<MyStruct>>
.
use std::fmt;
fn main() {
let maybe_my_struct: Option<Box<MyStruct>> = Some(Box::new(MyStruct{foo:42}));
println!("{}", maybe_my_struct);
}
struct MyStruct {
foo: i32,
}
impl fmt::Display for Option<Box<MyStruct>> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Some(MyStruct) => write!(formatter, "{}", self.foo),
None => write!(formatter, "No struct"),
}
}
}
我得到的错误是:
error: the impl does not reference any types defined in this crate;
only traits defined in the current crate can be implemented for arbitrary types [E0117]
我试过为 Option
类型设置别名,而不是实现 Display for MyOption<Box<MyStruct>>
,但结果相同。我做错了什么?
如您所见,您无法为您未编写的类型实现您未编写的特征。这是所谓的 "coherence" 的一部分,它的存在是为了防止非常奇怪的事情,比如链接到库突然导致程序的不相关部分改变行为。
别名 Option
到 MyOption
都不起作用 或者 因为,正如你所说,它是一个 别名 .也就是说,它只是同一事物的另一个名称,并不是实际的不同类型。
现在,如果您像这样围绕 Option
编写 wrapper:
struct MyOption<T>(Option<T>);
then MyOption
将是一个新的、独特的类型,您可以为其实现特征。当然,您需要编写方法来包装和解包您正在存储的实际 Option
。
...但这完全无关紧要,因为您 也可以 为您的结构派生 Debug
并使用它。
fn main() {
let maybe_my_struct: Option<Box<MyStruct>> = Some(Box::new(MyStruct{foo:42}));
println!("{:?}", Some(maybe_my_struct));
}
#[derive(Debug)]
struct MyStruct {
foo: i32,
}
或者,如果您真的想要 Option<Box<MyStruct>>
组合的自定义显示逻辑,您可以使用标记值(顺便说一下,标准库中的 Path
使用了相同的方法)。像这样:
use std::fmt;
fn main() {
let maybe_my_struct: Option<Box<MyStruct>> = Some(Box::new(MyStruct{foo:42}));
println!("{:?}", maybe_my_struct);
// Instead of displaying directly, display via a custom marker.
println!("{}", maybe_my_struct.display());
println!("{}", None::<Box<MyStruct>>.display());
}
#[derive(Debug)]
struct MyStruct {
foo: i32,
}
// This is the marker we'll use to define our custom Display impl.
struct MmsDisplay<'a>(&'a Option<Box<MyStruct>>);
// This trait lets us extend Option<Box<MyStruct>> with a new method.
trait CustomMmsDisplay {
fn display<'a>(&'a self) -> MmsDisplay<'a>;
}
impl CustomMmsDisplay for Option<Box<MyStruct>> {
fn display<'a>(&'a self) -> MmsDisplay<'a> {
MmsDisplay(self)
}
}
// And here's the display logic.
impl<'a> fmt::Display for MmsDisplay<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Some(ref ms) => write!(formatter, "{}", ms.foo),
None => write!(formatter, "No struct"),
}
}
}