Rust-07-结构体

结构体

和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵活:不需要依赖顺序来指定或访问实例中的值。可以当作是java对象。使用struct关键字定义

定义结构体

struct User {
    flag: bool,
    username: String,
    email: String,
    id: u32
}

// 使用没有命名字段的元组结构体来创建不同的类型,称为元组结构体
struct Color(i32, i32, i32);

// 类单元结构体
// 类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用。
struct AlwaysEqual;
fn main() {
 let subject = AlwaysEqual;
}

一旦定义了结构体后,为了使用它,通过为每个字段指定具体值来创建这个结构体的 实例。

实例化

let mut user = User {
    flag: true,
    username: String::from("tom"),
    email: String::from("hello@email.com"),
    id : 1
};
// 使用.进行访问
user.flag = false;
//结构体更新语法,使用..复用
let user2 = User {
    username: String::from("jerry"),
    ..user
};

//使用没有命名字段的元组结构体来创建不同的类型,称为元组结构体
struct Color(i32, i32, i32);
let black = Color(0, 0, 0);


// 没有任何字段的类单元结构体

示例程序

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    println!(
        "The area of the rectangle is {} square pixels.",
        area(&rect1)
    );
}
fn area(rectangle: &Rectangle) -> u32 {
    rectangle.width * rectangle.height
}

方法

方法与函数类似:它们使用 fn 关键字和名称声明,可以拥有参数和返回值,同
时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的,因为它们在结构体的上下文中被定义,并且它们第一个参数总是 self ,它代表调用该方法的结构体实例

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
impl Rectangle {
//这里选择 &self 的理由跟在函数版本中使用 &Rectangle 是相同的:我们并不想获取所有权,只希望能够读取结构体中的数据,而不是写入。类似于使用指针
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

使用方法替代函数,除了可使用方法语法和不需要在每个函数签名中重复 self 的类型之外,其主要好处在于组织性。我们将某个类型实例能做的所有事情都一起放入 impl 块中,而不是让将来的用户在我们的库中到处寻找 Rectangle 的功能。
在 C/C++ 语言中,有两个不同的运算符来调用方法:. 直接在对象上调用方法,而 -> 在一个对象的指针上调用方法,这时需要先解引用指针。换句话说,如果 object 是一个指针,那么 object->something() 就像(*object).something() 一样。
Rust 并没有一个与 -> 等效的运算符;相反,Rust 有一个叫 自动引用和解引用的功能。方法调用是 Rust 中少数几个拥有这种行为的地方。它是这样工作的:当使用 object.something() 调用方法时,Rust 会自动object 添加 & 、&mut 或 * 以便使 object 与方法签名匹配。这种自动引用的行为之所以有效,是因为方法有一个明确的接收者———— self 的类型。在给出接收者和方法名的前提下,Rust 可以明确地计算出方法是仅仅读取(&self ),做出修改(&mut self )或者是获取所有权(self )

关联函数

所有在 impl 块中定义的函数被称为 关联函数(associated functions),因为它们与 impl 后面命名的类型相关。我们可以定义不以 self 为第一参数的关联函数(因此不是方法),因为它们并不作用于一个结构体的实例。我们已经使用了一个这样的函数:在 String 类型上定义
的 String::from 函数

struct Rectangle {
    width:u32,
    height:u32
}

impl Rectangle {
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}

fn main() {
    let sq = Rectangle::square(10);
}

关键字 Self 在函数的返回类型中代指在 impl 关键字后出现的类型,在这里是 Rectangle,每个结构体也允许有多个impl块

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Rust 中,你可以使用结构和数组的初始化语法来创建和初始化实例。下面是一些示例: ### 结构初始化 ```rust struct Point { x: i32, y: i32, } fn main() { // 直接初始化结构的字段 let p1 = Point { x: 10, y: 20 }; // 部分字段初始化,其他字段使用默认值 let p2 = Point { x: 5, ..p1 }; // 通过解构元组来初始化结构字段 let (x, y) = (15, 25); let p3 = Point { x, y }; println!("p1: x = {}, y = {}", p1.x, p1.y); println!("p2: x = {}, y = {}", p2.x, p2.y); println!("p3: x = {}, y = {}", p3.x, p3.y); } ``` 在上面的示例中,我们定义了一个名为 `Point` 的结构,它有两个字段 `x` 和 `y`。然后,我们使用不同的方式来初始化结构实例 `p1`、`p2` 和 `p3`。最后,我们打印每个实例的字段值。 ### 数组初始化 ```rust fn main() { // 声明并初始化一个数组 let arr1: [i32; 5] = [1, 2, 3, 4, 5]; // 使用重复值初始化数组 let arr2 = [0; 3]; // 等同于 [0, 0, 0] println!("arr1: {:?}", arr1); println!("arr2: {:?}", arr2); } ``` 在上面的示例中,我们声明了一个包含 5 个 `i32` 类型元素的数组 `arr1`,并使用具的值来初始化它。另外,我们还使用 `[0; 3]` 的语法来初始化一个包含三个 0 的数组 `arr2`。最后,我们打印两个数组的值。 需要注意的是,Rust 的数组长度是固定的,一旦定义就无法改变。如果你需要动态大小的数组,可以考虑使用 `Vec` 类型。 这些是在 Rust 中初始化结构和数组的基本方法。你可以根据需要进行适当的调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值