Access a field from a struct casted with Box

2019-09-04 05:48发布

I have the following code, that I think is pretty self-explanatory. The problem I'm facing is in the render function:

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

Where the compiler complains:

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

Full code:

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

标签: rust
1条回答
做自己的国王
2楼-- · 2019-09-04 06:21

Yes, traits do not have access to the fields of their implementors. You need to provide accessor methods. These are small and should be optimized away:

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

Basically, traits are contracts that objects must adhere to, and the language of those contracts is the function names, the argument types, and the return types. If a trait needs to be able to get a view or a value, then that needs to be a part of the trait.

Note that implementations of traits do have access to the fields of the struct they are implementing the trait on. Since the implementation is specialized for one type, that guarantees that you have access to the appropriate fields.

查看更多
登录 后发表回答