Rust --结构体的定义和实例化

轩辕暗神 9月前 ⋅ 248 阅读

结构体是一种数据格式,也可以说是一种数据类型,其比元组,数组等数据类型操作起来更加灵活,主要是因为结构体内的元素值可以是不同的数据类型,并且不需要按顺序去访问。如果你接触过其他的面向对象的编程语言,结构体就类似于类(Class)的概念。

结构体的定义

定义结构体,需要使用 struct 关键字并为整个结构体提供一个名字。结构体的名字需要描述它所组合的数据的意义。接着,在大括号中,定义每一部分数据的名字和类型,我们称为 字段(field)。例如,示例 5-1 展示了一个存储用户账号信息的结构体:

文件名:src/main.rs

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

示例 5-1:User 结构体定义

结构体的赋值(实例化)

一旦定义了结构体后,为了使用它,通过为每个字段指定具体值来创建这个结构体的 实例。创建一个实例需要以结构体的名字开头,接着在大括号中使用 key: value 键 - 值对的形式提供字段,其中 key 是字段的名字,value 是需要存储在字段中的数据值。实例中字段的顺序不需要和它们在结构体中声明的顺序一致。换句话说,结构体的定义就像一个类型的通用模板,而实例则会在这个模板中放入特定数据来创建这个类型的值。例如,可以像示例 5-2 这样来声明一个特定的用户: 文件名:src/main.rs

fn main() {
    let user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };
}

示例 5-2:创建 User 结构体的实例

为了从结构体中获取某个特定的值,可以使用点号。举个例子,想要用户的邮箱地址,可以用 user1.email。如果结构体的实例是可变的,我们可以使用点号并为对应的字段赋值。示例 5-3 展示了如何改变一个可变的 User 实例中 email 字段的值: 文件名:src/main.rs

fn main() {
    let mut user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };

    user1.email = String::from("anotheremail@example.com");
}

注意整个实例必须是可变的;Rust 并不允许只将某个字段标记为可变。另外需要注意同其他任何表达式一样,我们可以在函数体的最后一个表达式中构造一个结构体的新实例,来隐式地返回这个实例。

示例 5-4 显示了一个 build_user 函数,它返回一个带有给定的 email 和用户名的 User 结构体实例。active 字段的值为 true,并且 sign_in_count 的值为 1。 文件名:src/main.rs

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username: username,
        email: email,
        sign_in_count: 1,
    }
}

示例 5-4:build_user 函数获取 email 和用户名并返回 User 实例

使用字段初始化简写语法

因为示例 5-4 中的参数名与字段名都完全相同,我们可以使用 字段初始化简写语法(field init shorthand)来重写 build_user,这样其行为与之前完全相同,不过无需重复 username 和 email 了,如示例 5-5 所示。 文件名:src/main.rs

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,
        email,
        sign_in_count: 1,
    }
}

示例 5-5:build_user 函数使用了字段初始化简写语法,因为 username 和 email 参数与结构体字段同名

这里我们创建了一个新的 User 结构体实例,它有一个叫做 email 的字段。我们想要将 email 字段的值设置为 build_user 函数 email 参数的值。因为 email 字段与 email 参数有着相同的名称,则只需编写 email 而不是 email: email。

使用结构体更新语法从其他实例创建实例

使用旧实例的大部分值但改变其部分值来创建一个新的结构体实例通常是很有用的。这可以通过 结构体更新语法(struct update syntax)实现。

首先,示例 5-6 展示了不使用更新语法时,如何在 user2 中创建一个新 User 实例。我们为 email 设置了新的值,其他值则使用了实例 5-2 中创建的 user1 中的同名值: 文件名:src/main.rs

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    // --snip--

    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    let user2 = User {
        active: user1.active,
        username: user1.username,
        email: String::from("another@example.com"),
        sign_in_count: user1.sign_in_count,
    };
}

示例 5-6:使用 user1 中的一个值创建一个新的 User 实例

使用结构体更新语法,我们可以通过更少的代码来达到相同的效果,如示例 5-7 所示。.. 语法指定了剩余未显式设置值的字段应有与给定实例对应字段相同的值。 文件名:src/main.rs

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    // --snip--

    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}

示例 5-7:使用结构体更新语法为一个 User 实例设置一个新的 email 值,不过其余值来自 user1 变量中实例的字段

结构体的使用


全部评论: 0

    我有话说: