在其他很多编程语言中,有类(Class)的存在,在Rust中,我们没有类(Class)的概念,我们使用结构体(Struct)。
与一个结构体相关的有以下几个部分:
声明一个结构体及其字段的格式如下:
pub struct RedFox {
enemy: bool,
life: u8,
}
以struct
关键词开头,后面紧跟结构体的名称(以大写字母开头的驼峰式命名),大括号中是结构体的数据字段,每个字段由字段名称及它的类型声明组成, 字段间用,
分隔。
最后一个字段后面也可以加上,
, 并且我们推荐大家这样做,以防在以后添加新字段时忘记在前面的字段后添加,
。
正如我们在前面的章节中提到的, Rust中的函数默认都是私有的,结构体也是一样, 如果想在别的模块中使用结构体,需要加上pub
标识:
pub struct RedFox {
enemy: bool,
life: u8,
}
结构体的字段默认也是私有的,默认只能在结构体被定义的模块内被访问, 如果想在结构体被定义的模块之外访问结构体的字段,则需要将该字段也标识成pub
:
pub struct RedFox {
pub enemy: bool,
life: u8,
}
结构体的数据字段本身也可以是一个结构体:
pub struct RedFox {
enemy: bool,
life: u8,
profile: Profile,
}
struct Profile {
name: String,
age: u8,
}
实例化一个结构体时,我们需要为这个结构体的每个字段都指定一个值。 一般来说,我们会为结构体实现一个关联函数,作为结构体的构造函数来创建一个具有默认值的结构体实例:
struct RedFox {
enemy: bool,
life: u8,
}
impl RedFox {
fn new() -> Self {
Self {
enemy: true,
life: 70,
}
}
}
结构体的方法和关联函数在一个叫impl
的代码块中实现,与结构体的定义是不同的代码块。这个代码块以impl
开头, 后面紧跟结构体的名称, 然后在其后的大括号中, 实现结构体的方法和关联函数。
上述代码中的fn new() -> Self
被称为结构体的关联函数,因为它没有使用self
或&self
作为其第一个参数。 这样的函数在一些其他语言(如Python)中被称为类方法,可以直接通过类名而不是类的实例调用。
在Rust中, new
函数是我们约定俗成的一个关联函数,用于创建一个具有默认值的结构体实例。在结构体的方法或关联函数中, 首字母大写的Self
等价于结构体的名称本身, 因此上面的关联函数也可以这样写:
impl RedFox {
fn new() -> RedFox {
RedFox {
enemy: true,
life: 70,
}
}
}
但我们更推荐使用Self
。
结构体方法也是在impl
代码块中进行实现的, 与关联函数不同的是,结构体方法总是以self
或&self
或&mut self
作为第一个参数。
impl RedFox {
// 关联函数
fn function() ...
// 方法
fn move(self) ...
fn borrow(&self) ...
fn mut_borrow(&mut self) ...
}
关联函数可以直接通过结构体名称调用, 而方法只能通过结构体的示例调用。
let fox = RedFox::new();
上面的代码会创建一个具有默认值的RedFox
结构体。注意Rust中的作用域操作符是::
, 我们使用它来访问类似命名空间中的部分内容。例如在前面的章节中, 我们在use
语句中也使用了::
来访问模块中的函数。在这个例子中,我们则是使用::
来访问一个结构体的关联函数。
一旦我们有了一个实例,我们就能像在大多数语言一样,通过这个实例,使用.
操作符来获取或设置特定字段的值,或者调用方法。
let fox = RedFox::new();
let life_left = fox.life;
fox.enemy = false;
fox.some_method();
本章我们介绍了Rust中的结构体的定义及其关联函数与方法的使用,下一章将介绍Rust中另一个非常重要的概念, Trait。