从使用 Box<Trait> 转换的结构访问字段

Access a field from a struct casted with Box<Trait>

我有以下代码,我认为它是不言自明的。我面临的问题是在 render 函数中:

fn render(&self) -> &'static str {
    self.view.value
}

编译器抱怨的地方:

attempted access of field `view` on type `&Self`, but no field with that name was found`

完整代码:

struct View1 {
    value: &'static str,
}

struct View2 {
    value: &'static str,
    another_value: &'static str,
}

struct Pattern<T> {
    view: T,
}

trait Renderable {
    fn render(&self) -> &'static str {
        self.view.value
    }
}

impl <T> Renderable for Pattern <T> {}

fn patterns() -> Vec<Box<Renderable>> {
    vec![
        Box::new(Pattern { view: View1 { value: "x" } }),
        Box::new(Pattern { view: View1 { value: "y" } }),
    ]
}

fn main() {
    let p = patterns();

    for x in p.iter() {
        println!("{}", x.render());
    }
}

是的,特征无法访问其实现者的字段。您需要提供访问器方法。这些很小,应该优化掉:

trait View {
    fn value(&self) -> &'static str;
}

struct View1 {
    value: &'static str,
}

impl View for View1 {
    fn value(&self) -> &'static str { self.value }
}

struct View2 {
    value: &'static str,
    another_value: &'static str,
}

impl View for View2 {
    fn value(&self) -> &'static str { self.value }
}

trait Renderable {
    fn view(&self) -> &View;

    fn render(&self) -> &'static str {
        self.view().value()
    }
}

struct Pattern<T>
    where T: View
{
    view: T,
}

impl<T> Renderable for Pattern<T>
    where T: View
{
    fn view(&self) -> &View {
        &self.view
    }
}

fn patterns() -> Vec<Box<Renderable>> {
    vec![
        Box::new(Pattern { view: View1 { value: "x" } }),
        Box::new(Pattern { view: View2 { value: "y", another_value: "z" } }),
    ]
}

fn main() {
    let p = patterns();

    for x in p.iter() {
        println!("{}", x.render());
    }
}

基本上,特征是对象必须遵守的契约,而这些契约的语言是函数名称、参数类型和 return 类型。如果特质需要能够获得 viewvalue,那么这需要成为特质的一部分。

注意 traits 的实现 do 可以访问他们正在实现 trait 的结构的字段。由于实现专门针对一种类型,因此可以保证您可以访问适当的字段。