如何使用参数实现特征默认实现

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 箱子可能会有用。