使用struct来结构化关联数据

前言

struct或者结构体,是一种定制化的数据类型,用来将关联项打包以形成一个有意义的整体。在OOP中,结构体可以类比为对象的数据属性。这个与C++类似,不过class的概念被抛弃了。
主要内容

  • 比较结构体和元组tuple
  • 如何定义、实例化结构体
  • 如何定义关联函数即方法,即指定结构体的行为
    结构体和枚举是创建新类型的基石并利用编译器的类型检查系统。

定义、实例化结构体

结构体和元组类似,都包括多个关联数据,数据的类型可以不同。
不同于元组,结构体的值都需要命名,这就提供了更高的灵活性,不必依赖于位置。

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

fn main() {
    let mut user1 = User {
        email: String::from("[email protected]"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
    user1.email = String::from("[email protected]");
 }

先定义,后使用,与go的struct使用类似,比C++冗余,但是更清晰?
所有成员默认公开,mut只能修饰整个结构体,不能修饰单个成员。

简化初始化

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

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

果然都觉得冗长,可以不加成员名称。

用其它示例初始化新对象

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

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

    let user1 = User {
        email: String::from("[email protected]"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    let user2 = User {
        email: String::from("[email protected]"),
        ..user1
    };
}

除了email成员,user2其它都与user1相同。比之C++更灵活?C++要支持这种,那就要新定义一个构造函数了。
…user1必须最后一个,指明剩下的成员都由use1指定了。称之为结构体更新。
注意,这里是赋值操作,可能存在数据move移动。在例子中,user1赋值给user2之后,将不能被使用。因为username是String类型,没有实现Copy trait,它被转移给user2了。

使用没有命名字段的元组结构体来创建不同类型

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

给予类型相同,意义不同的元组不同类型,提供可读性、复用性?
当然,因为Point Color是不同类型,所以origin和black不能相互赋值的,虽然它们的底层实际相同。rust有没有类似C/C++的强制类型转换?

无任何成员的类单元(unit)结构体

类似(),即单元类型。可以为没有任何成员的类型实现trait。

struct AlwaysEqual;

fn main() {
    let subject = AlwaysEqual;
}

结构体数据的所有权

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

fn main() {
    let user1 = User {
        email: "[email protected]",
        username: "someusername123",
        active: true,
        sign_in_count: 1,
    };
}

username和email定义为引用而不是值,此时没有声明两者的生命期,编译出错。

| ^ expected named lifetime parameter

猜你喜欢

转载自blog.csdn.net/wenyuanhust/article/details/124032176