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

时间:2019-06-15 17:53:41

标签: rust traits

我想将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,如何实现呢?

1 个答案:

答案 0 :(得分:1)

Rust(目前)无法执行此操作。但是,很可能有替代的类似解决方案对您来说就足够了。如果您对该功能的进展感兴趣,可以签出https://github.com/rust-lang/rfcs/pull/1546https://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 / setter方法很灵活并被“覆盖”(不使用默认值),则添加中间State结构会使它覆盖默认的impl(例如,对于get_value在具有常量字符串的示例中)需要/在State结构中具有未使用的字段。示例:

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());
}

正如ÖmerErden所提到的,https://crates.io/crates/getset板条箱可能很有用。