I know of the visibility rules in Rust and the typical 'constructor' patterns in Rust, e.g. via associated functions, commonly named as new
or if all fields of the struct are public, via 'direct' construction, e.g. Struct {value: 0}
.
Just wish to get a sense of what is the appropriate idiom to achieve the following:
Exposing a public struct with all public fields but restricting direct construction.
e.g.
pub struct MyStruct {
pub val: u8,
}
impl MyStruct {
pub fn new(val: u8) {
MyStruct {val}
}
}
Ok for external crate to do this:
use your_crate::MyStruct;
let your_struct = MyStruct::new(8);
println!("{}", your_struct.val);
//8
But not Ok for external crate (call it 'your_crate' vs. 'my_crate' in which MyStruct
is defined) to do this:
use my_crate::MyStruct;
let your_struct = MyStruct {val: 8};
// above should return compile error
I am aware that there are two methods to achieve this.
- Using
getter
andsetter
methods and make fields private.
pub struct MyStruct {
val: u8,
}
impl MyStruct {
pub fn new(val: u8) {
MyStruct {val}
}
pub fn get_val(&self) -> &u8 {
self.val
}
pub fn set_val(&mut self, new_val: u8) {
*self.val = new_val;
}
}
This provides access to the fields indirectly via method calls instead of attribute access.
- Add a 'private' inconsequential field.
pub struct MyStruct {
pub val: u8,
_private: (),
}
This prevents direct construction but allows for direct attribute access and removes the need for implementing superfluous 'get' and 'set' methods.
My question is:
Which is the more appropriate idiom accepted by many in the community? Or what considerations should a library writer think through before deciding which idiom is more appropriate?
pub
opens up the possibility that a user will violate an invariant after construction. Perhaps consider the readonly crate?