45

Traits are used to group some functions to be implemented from a struct, but is it possible to access struct fields from within the trait?

I could imagine declaring fields inside the trait so that the fields are abstracted as well. I haven't found such a syntax; is there any other solution? Otherwise, it wouldn't be possible to have non-static methods using a trait, would it?

I know object oriented programming from C# and I'm playing around with Rust, trying to adapt the OOP functionality I already know from C#.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Reignbeaux
  • 1,333
  • 3
  • 12
  • 15

3 Answers3

48

This sounds like you're misunderstanding how traits work. Traits can't have fields. If you want to provide access to a field from a trait, you need to define a method in that trait (like, say, get_blah).

If you're asking whether you can access fields of a struct from within that struct's implementation of a trait, then yes. The struct knows it's own type, so there's no problem.

trait Pet {
    fn is_smelly(&self) -> bool;
}

struct Dog {
    washed_recently: bool,
}

impl Pet for Dog {
    fn is_smelly(&self) -> bool {
        !self.washed_recently
    }
}

If you're writing a default implementation of a trait (i.e. defining a method body within the trait), then no, you can't access fields. A default implementation can only use methods that are defined on the trait or in a super trait.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
DK.
  • 55,277
  • 5
  • 189
  • 162
  • 14
    While writing out accessor methods for struct members is tedious, it's important to note that the optimizer is likely to remove the function call, making it equally as efficient. – Shepmaster Jan 29 '15 at 16:49
  • 3
    Your edit is basically what I was talking about. But when I can't have fields in a default implementation, Rust really doesn't allow to use classical inheritance patterns, does it? Like, here is an example: C# has a class FileStream which inherits from Stream. How would you do something like that using rust when you aren't able to access the fields of the struct? – Reignbeaux Jan 29 '15 at 16:54
  • 2
    That's correct - Rust does *not* have classical inheritance. There are very good composition abilities, as structs live inside other structs with no extra overhead. – Shepmaster Jan 29 '15 at 17:05
  • 1
    So how would that look like? Just having a field of another struct, or is there some kind of syntactic sugar as we have in Go (virtual fields) to access the members of the field directly? – Reignbeaux Jan 29 '15 at 19:38
  • @Reignbeaux sadly, there isn't a nice way of accessing a nested structs field directly, pretending that the nesting doesn't exist. You have to say `foo.nested.field`. – Shepmaster Jan 29 '15 at 22:22
28

It would be useful to define fields in a trait's default implementation, so a struct implementing the trait would always have the same fields.

Apparently, the Rust team thinks the same but it is still a work in progress according to this RFC. It's a big change and it has been postponed, so I think the short answer is: you can't do it yet, but you might be able to do it in the future.

For now, you'll have to make do with less powerful traits.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Fuujin
  • 480
  • 5
  • 9
8

You can make accessor function in default trait implementation, that must return field value/ref in child implementations, returning default value. Use it in other fn's in default implementation, and redefine accessor's in child implementation. Default implementation fn's will use redefined accessors as it's virtual fn's.

  • 1
    This seems like a good workaround. Default implementations of traits can't access struct fields directly (since traits can't have member variables unlike Java and many other OOP languages), but they can access getters/setters if you put their declaration in the trait itself, and it provides the same functionality as accessing struct fields IMO. – Meet Sinojia Aug 19 '20 at 18:36