如何在多态类型上调用Display特性



我有:

use std::fmt;
struct TeamMember {
    name: String,
    age: u32,
}
struct Manager {
    name: String,
    age: u32,
}
impl fmt::Display for TeamMember {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
         write!(f, "TeamMember; name => {}, age => {}", self.name, self.age)
      }
}
impl fmt::Display for Manager {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
         write!(f, "Manager; name => {}, age => {}", self.name, self.age)
      }
}
trait Employee {}
impl fmt::Display for Employee {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
         write!(f, "{}", *self)
      }
}
fn main() {
    let t = TeamMember { name: "abc".to_string(), age: 23 };
    let t2 = Manager { name: "xyz".to_string(), age: 18 };
    let mut v: Vec<&Employee> = Vec::new();
    v.push(&t);
    v.push(&t2);
    for it in &v {
        println!("i am a {}", *it);
    }
}

我想多态地调用trait对象的向量所引用的2个具体类型的显示。我得到以下编译错误:

<std macros>:2:21: 2:52 error: the trait `core::marker::Sized` is not implemented for the type `Employee` [E0277]
<std macros>:2 $ dst . write_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:2:21: 2:52 note: in this expansion of format_args!

向量迭代应该为具体类型调用Display函数。。。

这终于奏效了,谢谢:

use std::fmt;
struct TeamMember {
    name: String,
    age: u32,
}
struct Manager {
    name: String,
    age: u32,
}
impl fmt::Display for TeamMember {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TeamMember!; name => {}, age => {}", self.name, self.age)
    }
}
impl fmt::Display for Manager {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Manager!; name => {}, age => {}", self.name, self.age)
    }
}
trait Employee: fmt::Display {}
impl Employee for TeamMember {}
impl Employee for Manager {}
fn main() {
    let t = TeamMember {
        name: "abc".to_string(),
        age: 23,
    };
    let t2 = Manager {
        name: "xyz".to_string(),
        age: 18,
    };
    let mut v: Vec<&Employee> = Vec::new();
    v.push(&t);
    v.push(&t2);
    for it in &v {
        println!("i am a {}", *it);
    }
}

当您编写以下内容时:

write!(f, "{}", *self)

您假设*self的类型(即Employee)实现了Display,这不受类型约束的保证。所以你应该这样做:

trait Employee: fmt::Display {}

作为副作用,它允许您删除impl fmt::Display for Employee

由于Employee没有方法,因此不需要创建另一个特性。您可以直接使用Display

use std::fmt::Display;
fn main() {
    let t = TeamMember { name: "abc".to_string(), age: 23 };
    let t2 = Manager { name: "xyz".to_string(), age: 18 };
    let v = vec![&t as &Display, &t2];
    for it in &v {
        println!("i am a {}", *it);
    }
}

如果你想拥有一个不需要实现DisplayEmployee特征(正如Valentin-Lorentz的回答所要求的那样),你可以创建另一个同时需要两者的特征:

use std::fmt::Display;
trait Employee {}
impl Employee for TeamMember {}
impl Employee for Manager {}
trait PrintableEmployee: Employee + Display {}
impl<T> PrintableEmployee for T where T: Employee + Display {}
fn main() {
    let t = TeamMember { name: "abc".to_string(), age: 23 };
    let t2 = Manager { name: "xyz".to_string(), age: 18 };
    let v = vec![&t as &PrintableEmployee, &t2];
    for it in &v {
        println!("i am a {}", *it);
    }
}

最新更新