Rust getter and setter methots

Hello, I have been actively developing Java for many years and now I plan to develop my new projects with the Rust language by exploring the wonderful features of the Rust language. But what is the approach in rust language instead of getter/setter methods in java? Declaring the attributes within the structure as public or using getter/setter methods? Thanks in advance to everyone who answers :slight_smile:

2 Likes

"getter" methods are quite common, "setter" methods not so much (also declaring fields pub is a bit unusual). It really depends what you are doing, there is no absolute rule. Traits only have methods.

2 Likes

Thank you George. What approach is used instead of setter methods? I think it will take some time for some approaches to be adopted.

Well, it really depends what a struct is for, but for example for structs in the standard library like Vec, BTreeMap, HashMap etc. you will find methods that modify the struct in controlled ways, doing thing like inserting new elements, removing elements, or getting existing elements, getting the length or number of elements. This is pretty typical I would say.

@geebee22 is spot on about "it depends" and gave some really good examples of how mutations happen for data structures in Rust without having public members of the struct.

If you want examples of when members are public, check out the syn crate. Most of its structs' members are pub.

An important difference between Rust and most languages is that private fields are accessible from other functions within the same module. So any structures that are tightly coupled enough to mess with each others insides can live in the same module. Only the higher level APIs need to be public. For very large modules pub(super) and pub(crate) can enable splitting up it up into smaller modules.

Another possible trick is fields that are often set from outside (like parameters) can be their own struct with all public fields. Then owned versions of those can be passed in to change things, or an method could return a &mut to the internally stored copy.

On a related side note for advanced Rust, the private access within a module is why properly making a safe API to unsafe code is done at the module level.

3 Likes

For example, I want to develop rest api with Actix web. How do I define my data models and data transfer objects?

Getters/setters are useful when

  • The field is private (for downstream)
  • It's in the form of a trait (like AsRef<T>), independently of privacy

If your field is public, getters/setters have limited usefulness. Downstream can just read/write the field directly. (There's an accepted RFC for read-only fields, but it's not implemented yet, much less stable.)

If you have both a getter and a setter, keeping the field private still has benefits; you can rename the field, move it to a sub-struct, box it, etc. Perhaps most importantly: You can maintain invariants in a setter, you can't maintain them if the field is public.[1]


Code for which the field is visible, like your code in the same module, will rarely use getters and setters. The reason is that they take on this pattern:

//     vvvvv
fn get(&self) -> &SomeFieldType { todo!() }
fn set(&mut self, value: SomeFieldType) -> SomeFieldType { todo!() }
//     ^^^^^^^^^

The pattern requires borrowing the entirety of self, which is often too restrictive. Here's a related article.


  1. Until read-only fields anyway. ↩ī¸Ž

2 Likes

Data transfer objects will commonly have all fields simply pub, since they don't have any invariants by themselves - every invariant is checked on conversion from DTO to the type used in business logic.

2 Likes

There are several crates on crates.io that will help you generate getters and setters, should you decide that you want them, e.g.

https://crates.io/crates/getset

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.