我有一些代码返回类型的性状对象MyTrait
,以便它可以返回的几种不同的结构之一。我想为trait对象实现Display
trait,以便我可以打印该对象,并将细节委托给各种结构,因为它们各自需要自己的自定义格式化程序。
我可以通过在MyTrait
定义中包括一种格式化方法,然后为Display
实现MyTrait
并委托-来实现此目的,就像这样:
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)
}
}
然而,我已经有Display
对于每个结构体,其执行实现性状MyTrait
。这意味着我为每个结构都使用了两种方法,它们执行相同的操作-fmt()
方法可直接在结构上满足Display
特性,以及my_fmt()
方法,该方法由上面的代码。这看起来笨拙且重复。有更简单的方法吗?
这是一个完整的示例程序,阐明了这一点。它比我想要的要长一点(它基于我先前的问题Calling functions which return different types with shared trait and pass to other functions的答案,但我想不出一种更简单的方式来说明这一点。当然,在这个玩具示例中,结构和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
}
}
有人可以建议一种更简单,更清洁的方法吗?
答案 0 :(得分:1)
您可以使Display
成为MyTrait
的特征。
trait MyTrait: fmt::Display {
fn is_even(&self) -> bool;
}
这将使MyTrait
的特征对象成为Display
。仅当您希望MyTrait
的所有实现者都实现Display
时,此方法才有效,但是以前的解决方案也是如此。