Public "getter method" vs pub field

Hey there,

Quite a beginner question but well, everyone starts somewhere. Between those 2 methods, which one is preferred ?

Method1

pub struct Stroke {
    pub duration: usize
}

Method2

pub struct Stroke {
    duration: usize
}

impl Stroke {
    pub fn duration(&self) -> &usize {
        &self.duration
    }
}

I myself tend to use the second method because… I don’t know, maybe the encapsulation principle I learnt in OOP sticks to me. Are those 2 methods equivalent ? Is there a preferred method ?

Thanks a lot

Gefn

1 Like

The pub field allows a few more things that you may or may not want:

  • Construction: users can create a Stroke { duration: 42 }.
    • This also means it’s a breaking change for you to add or remove any fields.
    • You can add a private field to avoid this, even just a dummy _private: () that takes no space.
  • Mutation: if the user has some mut var: Stroke or &mut Stroke, they can change the duration. This might be convenient, but you need to be careful if there are any invariants to uphold on that field.
  • Partial borrow: if a user binds let var = &stroke.duration; they can still use other fields of the Stroke without any complaint from the borrow checker.
    • This especially applies with mutation, since that’s an exclusive borrow. With your getter, borrowing duration will lock the whole struct since it goes through the full &self. The user could still do other immutable accesses, but not anything that wants mutable access to any part of the struct.
4 Likes

The rough rule of thumb I use is

  • If there’s a combination of values of fields which breaks some invariant, than make all fields private and provide a getter
  • If any combination of fields values makes sense, make all fields public
10 Likes

Method1 and Method2 are not equivalent, because &self in pub fn duration(&self) is not mutable :slight_smile: