I want to implement getter and setter into the trait. For example:
trait StringValue {
value: String;
fn setValue(&self, value: String) {
self.value = value;
}
fn getValue(&self) -> String {
return self.value;
}
}
struct S;
impl StringValue for S {}
fn main() {
let s: S = S {};
s.setValue(String::from("test"));
println!("{}", s.getValue());
}
cargo build:
error: missing `fn`, `type`, or `const` for trait-item declaration
--> src/main.rs:1:20
|
1 | trait StringValue {
| ____________________^
2 | | value: String;
| |____^ missing `fn`, `type`, or `const`
error[E0609]: no field `value` on type `&Self`
--> src/main.rs:5:14
|
5 | self.value = value;
| ^^^^^
error[E0609]: no field `value` on type `&Self`
--> src/main.rs:9:21
|
9 | return self.value;
| ^^^^^
error: aborting due to 3 previous errors
Questions:
Can I use parameters into traits?
How can I fix the code?
If I want to use getter and setter into two different classes, how to implement it?
There is no way to do this in Rust (Currently). However, it's very likely that an alternative, similar, solution is enough for you. If you're interested in progress in that feature, you can check out https://github.com/rust-lang/rfcs/pull/1546 and https://github.com/nikomatsakis/fields-in-traits-rfc.
As for alternative solutions, simply leaving the implementation of the getter/setter to the struct is one option:
trait StringValue {
fn setValue(&mut self, value: String);
fn getValue(&self) -> &String;
}
struct S {
value: String,
}
impl StringValue for S {
fn setValue(&mut self, value: String) {
self.value = value;
}
fn getValue(&self) -> &String {
return &self.value;
}
}
fn main() {
let mut s: S = S {
value: String::from(""),
};
s.setValue(String::from("test"));
println!("{}", s.getValue());
}
But that might get slightly repetitive, specially if you have many such methods. You could try putting them in a separate state struct, add a getter for that state struct and use it to get the fields in the trait's default impl for all the getters/setters, and then just leave an impl of the getter for the state struct up to the containing one to define. However, it should be noted that if you expect these getter/setters to be flexible and be "overriden" (Not use the default), adding the intermediate State struct will make it so a struct overriding the default impl (For, say, get_value in the example with a constant string) needs/has an unused field in the State struct.Example:
trait StringValue {
fn get_state(&self) -> &State;
fn get_state_mut(&mut self) -> &mut State;
fn set_value(&mut self, value: String) {
self.get_state_mut().value = value
}
fn get_value(&self) -> &str {
self.get_state().value.as_str()
}
fn set_value2(&mut self, value: String) {
self.get_state_mut().value2 = value
}
fn get_value2(&self) -> &str {
self.get_state().value2.as_str()
}
}
struct State {
value: String,
value2: String,
}
struct OtherStruct {
state: State,
}
impl StringValue for OtherStruct {
fn get_state_mut(&mut self) -> &mut State {
&mut self.state
}
fn get_state(&self) -> &State {
&self.state
}
}
fn main() {
let mut s = OtherStruct {
state: State {
value: String::from(""),
value2: String::from(""),
},
};
s.set_value(String::from("test"));
dbg!(s.get_value());
s.set_value2(String::from("test2"));
dbg!(s.get_value2());
}
As mentioned by Ömer Erden, the https://crates.io/crates/getset crate might be useful.