如何在类型已实现Display的特征对象上实现Display



我有一些代码,它返回类型为MyTrait的trait对象,这样它就可以返回几个不同结构中的一个。我想为trait对象实现Displaytrait,这样我就可以打印对象,并将详细信息委托给各个结构,因为它们都需要自己的自定义格式化程序。

我可以通过将格式化方法作为MyTrait定义的一部分来实现这一点,然后为MyTrait实现Display并进行委派,如下所示:

trait MyTrait {
fn is_even(&self) -> bool;
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
}
impl fmt::Display for MyTrait {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.my_fmt(f)
}
}

然而,我已经为实现MyTrait的每个结构实现了Display特性。这意味着我最终为每个结构提供了两个做同样事情的方法——直接在结构上满足Display特性的fmt()方法,以及由上面的代码调用的my_fmt()方法。这看起来既笨拙又重复。有更简单的方法吗?

这里有一个完整的示例程序来说明这一点。它比我想要的要长一点(这是基于我之前问题的答案调用函数,这些函数返回具有共享特性的不同类型并传递给其他函数),但我想不出更简单的方法来说明这一点。当然,在这个玩具示例中,结构和fmt函数非常简单;在我的实际应用程序中,它们更为复杂。

use std::fmt;
trait MyTrait {
fn is_even(&self) -> bool;
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
}
struct First {
v: u8,
}
struct Second {
v: Vec<u8>,
}
impl MyTrait for First {
fn is_even(&self) -> bool {
self.v % 2 == 0
}
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v)
}
}
impl MyTrait for Second {
fn is_even(&self) -> bool {
self.v[0] % 2 == 0
}
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v[0])
}
}
fn make1() -> First {
First { v: 5 }
}
fn make2() -> Second {
Second { v: vec![2, 3, 5] }
}
// Implement Display for the structs and for MyTrait
impl fmt::Display for First {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v)
}
}
impl fmt::Display for Second {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v[0])
}
}
impl fmt::Display for MyTrait {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.my_fmt(f)
}
}
fn requires_mytrait<T: MyTrait + ?Sized>(v: &&T) {
println!("{:?}", v.is_even());
}
fn main() {
for i in 0..2 {
let v1;
let v2;
let v = match i {
0 => {
v1 = make1();
println!("> {}", v1); // Demonstrate that Display
// is implemented directly
// on the type.
&v1 as &MyTrait
}
_ => {
v2 = make2();
println!("> {}", v2); // Demonstrate that Display
// is implemented directly
// on the type.
&v2 as &MyTrait
}
};
requires_mytrait(&v);
println!("{}", v); // Here I print the trait object
}
}

有人能提出一个更简单、更干净的方法吗?

您可以使Display成为MyTrait的超性状。

trait MyTrait: fmt::Display {
fn is_even(&self) -> bool;
}

这将使MyTrait的特征对象成为Display。只有当您希望MyTrait的所有实现者都实现Display时,这才有效,但在以前的解决方案中也是如此。

最新更新