Rust 速成课/结构体, 函数与方法

我们要谈论一下结构体, 对于构建程序应用来说, 使用结构体能让你的程序显得更加结构化, emm, 上面这句话有点意义不明但又找不出任何毛病吼. 结构体它指的是一种复合数据结构, 可让打包一组多个相关的值到一起. 如果你熟悉面向对象的语言, 则结构就像对象的数据属性一样.

不过要注意哦, Rust 并不是面向对象的语言. 其实我本人不是很欣赏面向对象的哲学啦, 基本上我很少会使用面向对象的语言来编写应用. Erlang 语言的作者 Joe Armstrong 也非常不喜欢面向对象编程, 他曾经说了一段很有名的话: "面向对象编程的问题是, 默认带有环境. 你只想要一个香蕉, 但是得到了一只拿着香蕉的大猩猩, 甚至还有整个丛林". 记得这句话, 它很有用, 因为你经常可以引用这句话终结和新手之间一些无意义的争论.

结构体和对象的使用方式极为相似, 我们来分析一下它们的区别. 我想大家可能听说过这句话: 程序等于数据结构加算法. 那么结构体它是数据的集合, 而对象则是数据加算法的集合, 对象不但打包了一组数据, 还定义了应该如何去使用这组数据.

我们通过代码演示一下如何使用结构体, 函数和方法.

结构体

要定义一个结构, 我们需要输入关键字 struct 并命名整个结构. 然后, 敲入一对大括号内, 定义数据的名称和类型, 我们将其称为字段, 就像下面这样, 我定义了一个 User 结构体. 用户有它的名字, 作为字符串类型, 还有年龄, 无符号 32 位整型, 还有他拥有自己的电子邮箱.

struct User {
    username: String,
    age: u32,
    email: String,
}

我们完成了对结构体的定义, 为了使用该结构体, 我们可以通过为每个字段指定具体值来创建该结构的实例.

let someone = User {
    username: String::from("someone"),
    age: 18,
    email: String::from("someone@example.com"),
};

使用点符号可以从结构体中取得一个字段的值

println!("{}", someone.username);

我想提出一个问题, 如果我现在想修改 someone 的年龄, 我应该怎么做? 回忆一下, Rust 中的变量默认是不可变的, 要让一个变量可变必须加上 mut 修饰词是吗? 所以我们将 let someone 修改成 let mut someone, 然后就可以直接修改字段了.

函数

我们想让这个用户向你打个招呼, 他会首先向你打印 Hello, 然后再告诉你他的名字. 为此我们可以创建一个函数, 这个函数接收 User 类型的变量作为参数.

fn sayhello(user: &User) {
    println!("Hello, I'm {}", user.username);
}

然后就可以这么去使用它

sayhello(&someone);

方法

方法与函数相似: 它们使用 fn 关键字及其名称进行声明, 可以具有参数和返回值, 并且包含一些在其他地方调用时运行的代码. 但是, 方法与函数的不同之处在于它们是在结构体的上下文中定义的, 并且它们的第一个参数始终是 self, 它表示调用该方法的结构体实例.

我们接着上面的例子, 首先使用 impl 申明我们准备为 User 结构体定义方法, 然后将上面的 sayhello 函数复制过来, 将参数名改成 self, 即可.

impl User {
    fn sayhello(&self) {
        println!("Hello, I'm {}", self.username);
    }
}