怎么打印!选项<Box <struct >>?

Tor*_*ler 6 rust

我正在尝试打印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"),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

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]
Run Code Online (Sandbox Code Playgroud)

我试过别名Option类型,而不是实现Display for MyOption<Box<MyStruct>>,但这给出了相同的结果.我究竟做错了什么?

DK.*_*DK. 7

正如您所看到的,您无法实现您没有为未编写的类型编写的特征.这是所谓的"连贯性"的一部分,并且存在以防止真正奇怪的事情,例如链接到库突然导致程序的不相关部分改变行为.

别名Option是MyOption不起作用的,因为,正如你所说,它是别名.也就是说,它只是同一个东西的另一个名称,它不是一个实际的,不同的类型.

现在,如果你写一个包装周围Option,像这样:

struct MyOption<T>(Option<T>);
Run Code Online (Sandbox Code Playgroud)

然后 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,
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您确实需要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"),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)