如何使用参数实现特征默认实现
How to implement trait default implementation with parameter
我想将 getter 和 setter 实现到特征中。例如:
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());
}
货物构建:
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
问题:
我可以在特征中使用参数吗?
如何修复代码?
如果我想把getter和setter变成两个不同的类,如何实现呢?
在 Rust 中无法做到这一点(目前)。但是,很可能一个替代的、类似的解决方案对您来说就足够了。如果您对该功能的进展感兴趣,可以查看 https://github.com/rust-lang/rfcs/pull/1546 and https://github.com/nikomatsakis/fields-in-traits-rfc.
至于替代解决方案,简单地将 getter/setter 的实现留给结构是一种选择:
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());
}
但这可能会有些重复,特别是如果您有很多这样的方法。您可以尝试将它们放在一个单独的状态结构中,为该状态结构添加一个 getter 并使用它来获取特征默认实现中所有 getters/setters 的字段,然后只留下一个实现getter 用于状态结构,直到要定义的包含结构。但是,应该注意的是,如果您希望这些 getter/setter 是灵活的并且是 "overriden" (不使用默认值),添加中间状态结构将使其成为覆盖默认实现的结构(例如,示例中的 get_value 具有常量字符串) needs/has 状态中未使用的字段 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());
}
如 Ömer Erden 所述,https://crates.io/crates/getset 箱子可能会有用。
我想将 getter 和 setter 实现到特征中。例如:
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());
}
货物构建:
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
问题:
我可以在特征中使用参数吗?
如何修复代码?
如果我想把getter和setter变成两个不同的类,如何实现呢?
在 Rust 中无法做到这一点(目前)。但是,很可能一个替代的、类似的解决方案对您来说就足够了。如果您对该功能的进展感兴趣,可以查看 https://github.com/rust-lang/rfcs/pull/1546 and https://github.com/nikomatsakis/fields-in-traits-rfc.
至于替代解决方案,简单地将 getter/setter 的实现留给结构是一种选择:
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());
}
但这可能会有些重复,特别是如果您有很多这样的方法。您可以尝试将它们放在一个单独的状态结构中,为该状态结构添加一个 getter 并使用它来获取特征默认实现中所有 getters/setters 的字段,然后只留下一个实现getter 用于状态结构,直到要定义的包含结构。但是,应该注意的是,如果您希望这些 getter/setter 是灵活的并且是 "overriden" (不使用默认值),添加中间状态结构将使其成为覆盖默认实现的结构(例如,示例中的 get_value 具有常量字符串) needs/has 状态中未使用的字段 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());
}
如 Ömer Erden 所述,https://crates.io/crates/getset 箱子可能会有用。