Ok, the specific problem here is not being able to move out of borrowed content. This has been answered numerous times before under a variety of conditions, not to mention the chapter on the subject of ownership in the Rust Book.
The more interesting one is about getters and setters. Yes, you can write them in Rust, but they may not be the best choice.
Before I go on, I just want to note that there is absolutely no reason to require &mut self
on a getter… unless you intend to modify the value as part of removing the value, but then you’re not really dealing with a getter any more.
Secondly, you should not clone
in a getter. This is hugely wasteful if all the user wants to do is, for example, read from the value. It’s better to return an immutable borrow, from which the user can clone
if they need to.
Anyway, if you’re writing these because you want some kind of logic run in order to validate new values, keep using setters. Otherwise, you could do something like this:
#[derive(Default)]
struct Person {
first_name: String,
last_name: String,
}
impl Person {
// Immutable access.
fn first_name(&self) -> &str {
&self.first_name
}
fn last_name(&self) -> &str {
&self.last_name
}
// Mutable access.
fn first_name_mut(&mut self) -> &mut String {
&mut self.first_name
}
fn last_name_mut(&mut self) -> &mut String {
&mut self.last_name
}
}
fn main() {
let mut my_person = Person::default();
*my_person.first_name_mut() = String::from("John");
*my_person.last_name_mut() = "Doe".into();
println!("first_name: {}", my_person.first_name());
println!("last_name: {}", my_person.last_name());
// Can't do this efficiently with getter/setter!
{
let s = my_person.last_name_mut();
s.truncate(2);
s.push('w');
}
println!("first_name: {}", my_person.first_name());
println!("last_name: {}", my_person.last_name());
}
This gives users more-or-less direct access to the fields, without actually giving them direct access to the fields. In addition to writing new values, this also allows users to mutate existing values in-place, which can be important for large, heap-allocated things.
In addition, I made a few other changes:
-
You can just mechanically derive
Default
; there’s no reason in this case to write it yourself. -
Conventional style is
snake_case
for fields. -
The way you created the
Person
was needlessly roundabout.