在 Rust 中编写 getter/setter 属性 [英] Writing getter/setter properties in Rust

查看:165
本文介绍了在 Rust 中编写 getter/setter 属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a very simple getter/setting model that I would like to start using in Rust for simplicity reasons using struct and impl.

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

当我运行此代码段时,出现以下错误.

When I run this snippet I get the following error.

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 很陌生,所以有人可以向我指出错误吗?

Can someone point out the mistake to me since I'm very new to Rust?

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

Tips on writing this snippet better would be accepted too. I'm always looking for easier/faster readability.

推荐答案

好的,这里的具体问题是不能搬出借来的内容.这已经回答 无数 次数 之前 在各种条件下,更不用说 Rust 书中关于所有权主题的章节.

Ok, the specific problem here is not being able to move out of borrowed content. This has been answered numerous times before under a variety of conditions, not to mention the chapter on the subject of ownership in the Rust Book.

更有趣的是关于 getter 和 setter.是的,您可以用 Rust 编写它们,但它们可能不是最佳选择.

The more interesting one is about getters and setters. Yes, you can write them in Rust, but they may not be the best choice.

在我继续之前,我只想指出,绝对没有理由在 getter 上要求 &mut self ......除非你打算修改值作为删除值的一部分,但您实际上不再处理 getter.

Before I go on, I just want to note that there is absolutely no reason to require &mut self on a getter... unless you intend to modify the value as part of removing the value, but then you're not really dealing with a getter any more.

其次,你不应该clone在一个getter中.例如,如果用户想做的只是从值中读取,这将是非常浪费的.最好返回一个不可变的借用,用户可以从中clone 如果他们需要.

Secondly, you should not clone in a getter. This is hugely wasteful if all the user wants to do is, for example, read from the value. It's better to return an immutable borrow, from which the user can clone if they need to.

无论如何,如果你写这些是因为你想要运行某种逻辑来验证新值,请继续使用 setter.否则,您可以执行以下操作:

Anyway, if you're writing these because you want some kind of logic run in order to validate new values, keep using setters. Otherwise, you could do something like this:

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

这让用户或多或少可以直接访问这些字段,而实际上却没有让他们直接访问这些字段.除了写入新值之外,这还允许用户就地改变现有值,这对于大型堆分配的事物可能很重要.

This gives users more-or-less direct access to the fields, without actually giving them direct access to the fields. In addition to writing new values, this also allows users to mutate existing values in-place, which can be important for large, heap-allocated things.

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

In addition, I made a few other changes:

  • 你可以机械地推导出Default;在这种情况下没有理由自己编写.

  • You can just mechanically derive Default; there's no reason in this case to write it yourself.

字段的常规样式是 snake_case.

您创建 Person 的方式是不必要的迂回.

The way you created the Person was needlessly roundabout.

这篇关于在 Rust 中编写 getter/setter 属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆