如何在其多态类型上调用显示特征?

时间:2016-05-15 11:42:13

标签: rust

我有:

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);
    }
}

我想以多态方式调用特征对象矢量引用的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函数...

3 个答案:

答案 0 :(得分:2)

这终于奏效了,谢谢:

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);
    }
}

答案 1 :(得分:0)

当你这样写:

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

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

trait Employee: fmt::Display {}

作为副作用,您可以删除impl fmt::Display for Employee

答案 2 :(得分:0)

由于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);
    }
}

如果您希望没有要求Employee实施Display特征(根据Valentin Lorentz' answer的要求),您可以创建另一个要求两者的特征:

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);
    }
}