在Rust

时间:2016-02-14 10:14:11

标签: oop rust

我正在编写一个非常简单的getter / setting模型,为了简单起见,我想在Rust中使用structimpl

struct Person {
    firstName: String,
    lastName: String,
}

impl Person {
    fn get_first_name(&mut self) -> String { return self.firstName; }
    fn get_last_name(&mut self) -> String {  return self.lastName; }

    fn set_first_name(&mut self, x: String) { self.firstName = x; }
    fn set_last_name(&mut self, x: String) { self.lastName = x; }

    fn default() -> Person {
        Person {firstName: "".to_string(), lastName: "".to_string()}
    }
}

fn main() {
    let mut my_person : Person = Person{ ..Person::default() };

    my_person.set_first_name("John".to_string());
    my_person.set_last_name("Doe".to_string());

    println!("{}", my_person.firstName);
    println!("{}", my_person.lastName);
}

当我运行此代码段时,我收到以下错误。

src\main.rs:7:53: 7:57 error: cannot move out of borrowed content [E0507]
src\main.rs:7     fn get_first_name(&mut self) -> String { return self.firstName; }
                                                                  ^~~~
src\main.rs:8:53: 8:57 error: cannot move out of borrowed content [E0507]
src\main.rs:8     fn get_last_name(&mut self) -> String {  return self.lastName; }
                                                                  ^~~~
error: aborting due to 2 previous errors
Could not compile `sandbox`.

有人可以向我指出错误,因为我对Rust很新吗?

更好地编写此代码段的提示也将被接受。我一直在寻找更容易/更快的可读性。

2 个答案:

答案 0 :(得分:19)

好的,这里的具体问题是无法摆脱借来的内容。在各种条件下,这一直是answered numerous times before,更不用说the chapter on the subject of ownership in the Rust Book了。

更有趣的是吸气剂和二传手。是的,您可以在Rust中编写它们,但它们可能不是最佳选择。

在我继续之前,我只想注意在getter上有绝对没有理由要求 4. 104ms for the JPEG and 177ms for the PNG ...除非您打算在删除过程中修改该值价值,但是你不再真正处理吸气剂了。

其次,你不应该在getter中 &mut self。如果所有用户想要做的是例如从值中读取,那么这是非常浪费的。最好返回一个不可变的借位,如果需要,用户可以clone

无论如何,如果您正在编写这些文件是因为您希望运行某种逻辑以验证新值,请继续使用setter。否则,你可以这样做:

clone

这使用户可以或多或少地直接访问这些字段,而实际上可以直接访问这些字段。除了编写新值之外,这还允许用户就地改变现有值,这对于大量堆分配的东西很重要。

此外,我还做了一些其他改动:

  • 你可以机械地推导#[derive(Default)] struct Person { first_name: String, last_name: String, } impl Person { // Immutable access. fn first_name(&self) -> &String { &self.first_name } fn last_name(&self) -> &String { &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()); } ;在这种情况下没有理由自己写。

  • 字段的常规样式为Default

  • 您创建snake_case的方式是不必要的回合。

答案 1 :(得分:1)

你的getter方法借用了self。当您返回self.name时,您将从借用的参考文件中移动name,这是不允许的。您应该返回一份姓名副本。

此外,您不需要在getter方法中向self传递可变引用,因为您没有修改内部结构。

因此,你的getter方法应该是:

fn get_first_name(&self) -> &String { &self.firstName }
fn get_last_name(&self) -> &String {  &self.lastName }