Is it possible to access struct fields from within a trait?
Asked Answered
S

3

50

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#.

Spraddle answered 29/1, 2015 at 16:29 Comment(0)
J
55

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.

Josephjosepha answered 29/1, 2015 at 16:39 Comment(5)
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.Queer
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?Spraddle
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.Queer
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?Spraddle
@Spraddle 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.Queer
S
29

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.

Sharell answered 26/1, 2018 at 22:8 Comment(1)
End of April 2022! Still nothingJetport
S
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.

Socher answered 26/8, 2019 at 23:55 Comment(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.Mend

© 2022 - 2024 — McMap. All rights reserved.