【Rust-book】第五章 使用结构体来组织相关联的数据
第五章 使用结构体来组织相关联的数据
结构,或者结构体,是一种自定义数据类型,它允许我们命名多个相关的值并将它们组成一个有机的结合体。
可以把结构体视作对象中的数据属性
1 对比元组和结构体之间的异同,并演示如何使用结构体
2 讨论如何定义方法和关联函数,他们可以指定那些与结构体数据相关的行为
结构体和枚举体是用来创建类型的基本工具,在特定领域中的新类型同样可以享受到Rust编译时类型检查系统的所有优势。
定义并实例化结构体
结构体需要给每个数据赋予名字,可以清楚地表明它们地意义。
由于字段命名,不再需要依赖顺序索引来指定或访问实例中的值。
关键字struct被用来定义并命名结构体,一个良好的结构体名称应当能反映出自身数据组合的意义。在随后的花括号中声明所有数据的名字及类型,这些数据被称为字段。
1 struct User {
2 username: String,
3 email: String,
4 sign_in_count: u64,
5 active: bool,
6 }
在为每个字段赋予具体的值来创建结构体实例,赋值的顺序不需要严格对应在结构体中声明它们的顺序。
结构体的定义就像类型的通用模版一样,当我们将具体的数据填入模板时就创建出了新的实例。
1 let user1 = User {
2 email: String::from("someone@example.con"),
3 username: String::from("someusername123"),
4 active: true,
5 sign_in_count: 1,
6 };
可以通过点号来访问实例中的特定字段。
1 let mut user1 = User {
2 email: String::from("someone@example.con"),
3 username: String::from("someusername123"),
4 active: true,
5 sign_in_count: 1,
6 };
7
8 user1.email = String::from("anothermail@example.com");
一旦实例可变,那么实例中的所有字段都将是可变的。
Rust不允许我们将单独声明某一部分字段的可变性。
1 fn build_user( email: String, username: String) -> User {
2 User { // 在变量名与字段名相同时使用简化版的字段初始化方法
3 // 参数与结构体字段拥有完全一致的名称,所以可以使用名为字段初始化简写的语法(field init shorthand)
4 email,
5 username,
6 active: true,
7 sign_in_count: 1,
8 }
9 }
使用结构体更新语法根据其他实例创建新实例
1 let user2 = User {
2 email: String::from("another@example.com"),
3 username: String::from("anotherusername455"),
4 ..user1 // .. 表明剩下的那些还未被显示赋值字段都与给定实例拥有相同的值
5 };
使用不需要对字段命名的元组结构体来创建不同的类型
元组结构体, 元组结构体同样拥有用于表明自身含义的名称,无须在声明它时对其字段进行命名,仅保留字段的类型即可。
一般来说,当你想要给元组赋予名字,并使其区别与其他拥有同样定义的元组时,可以使用元祖结构体。
1 struct Color(i32, i32, i32);
2 struct Point(i32, i32, i32);
3
4 let black = Color(0,0,0);
5 let origin = Point(0,0,0);
这里的 black ,origin 是不同的类型,因为它们两个分别是不同元组结构体的实例,
所以定义的每一个结构体都拥有自己的类型,即便结构体中的字段拥有完全相同的类型。 例如,一个以Color类型作为参数的函数不能合法地接收Point类型的参数,即使它们都是由3个i32组成的。
可以通过模式匹配解构为单独的部分,也可以通过.及索引来访问特定字段
没有任何字段的空结构体
单元结构体,没有任何字段的结构体()。也称为空结构体
当需要在某些类型实现一个trait,却不需要在该类型中存储任何数据时,空结构体可以发挥作用。
1 //对于引用来说有生命周期的限制
2 struct User {
3 username: &str, // expected lifetime parameter
4 email: &str,
5 sign_in_count: u64,
6 active: bool,
7 }
8
9 fn main() {
10 let user1 = User {
11 email: "someone@example.com",
12 username: "someusername123",
13 active: true,
14 aign_in_count: 1,
15 };
16 }
一个结构体的示例程序
1 fn main() {
2 let width1 = 30;
3 let height1 = 50;
4
5 println!("The area of the rectangel is {} aquare pixels.", area(width1, height1));
7 }
8 fn area(width: u32, height: u32) -> u32 {
9 width * height
10 }
元组重构
1 fn main() {
2 let rect1 = (30, 50);
3
4 println!("The area of the rectangel is {} aquare pixels.", area(rect1));
5 }
6
7 fn area(dimensions: (u32, u32)) -> u32 {
8 dimensions.0 * dimensions.1
9 }
使用结构体来重构代码,增加有意义的描述信息
1 struct Rectangle {
2 width: u32,
3 height: u32,
4 }
5
6 fn main() {
7 let rect1 = Rectangle { width: 30, height: 50 };
8 println!("The area of the rectangel is {} aquare pixels.", area(&rect1));
9 }
10
11 fn area(rectange: &Rectangle) -> u32 { //不可变借用&Rectangle ,不会获得它的所有权
12 rectangle.width * rectangle.height
13 }
通过派生trait增加适用功能
1 #[derive(Debug)]
2 struct Rectange {
3 width: u32,
4 height: u32,
5 }
6
7 fn main() {
8 let rect1 = Rectangle { width: 30, height: 50 };;
9 println!("rect1 is {:?}", rect1);
10 }
方法
方法总是被定义在某个结构体、枚举体或者triat对象,并且它们的第一个参数永远都是self,用于指代调用该方法的结构体实例。
1 #[derive(Debug)]
2 struct Rectangle {
3 width: u32,
4 height: u32,
5 }
6
7 impl Rectangle {
8 fn area(&self) -> u32 { // self: &Self ---> Self is Rectangle
9 self.width * sellf.height
10 }
11 }
12
13 fn main() {
14 let rect1 = Rectangle { width: 30, height: 50 };
15 println!("The area of the rectangel is {} aquare pixels.", rect1.area());
16 }
为了在Rectangle的上下文环境中定义这个函数,需要将area函数移动到impl 关键字起始的代码块中,并把签名中的第一个参数(也是唯一的那个参数)和函数中使用该参数的地方改为self.
方法调用是通过实例后面加点好,并更上方法名、括号及可能的参数来实现。
带有更多参数的方法
1 fn main() {
2 let rect1 = Rectangle { width: 30, height: 50 };
3 let rect2 = Rectangle { width: 10, height: 40 };
4 let rect3 = Rectangel { width: 60, height: 45 };
5
6 println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
7 println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
8 }
9
10 #[derive(Debug)]
11 struct Rectangle {
12 width: u32,
13 height: u32,
14 }
15
16 impl Rectangle {
17 fn area(&self) -> u32 { // self: &Self ---> Self is Rectangle
18 self.width * sellf.height
19 }
20
21 fn can_hold(&self, other: &Rectangle) -> bool {
22 self.width > other.width && self.height > other.height
23 }
24 }
25
26 // 关联函数
27 impl Rectangle {
28 fn squaer(size: u32) -> Rectange {
29 Rectange { width: size, height: size }
30 }
31 }
关联函数常常用作构造器来返回一个结构体的新实例。
类型名称后面添加::来调用关联函数
:: 语法不仅被用于关联函数,还被用于模块创建的明命名空间。
多个imple块
1 impl Rectangle {
2 fn area(&self) -> u32 { // self: &Self ---> Self is Rectangle
3 self.width * sellf.height
4 }
5 }
6
7 impl Rectangle {
8 fn can_hold(&self, other: &Rectangle) -> bool {
9 self.width > other.width && self.height > other.height
10 }
11 }
【Rust-book】第五章 使用结构体来组织相关联的数据的更多相关文章
- python 教程 第十五章、 结构布局
第十五章. 结构布局 #!/usr/bin/env python #(1)起始行 "this is a module" #(2)模块文档 import sys #(3)模块导入 d ...
- 全国计算机等级考试二级教程-C语言程序设计_第14章_结构体、共用体和用户定义类型
函数的返回值是结构体类型 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> struct ...
- GO开发[五]:golang结构体struct
Go结构体struct Go语言的结构体(struct)和其他语言的类(class)有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性 ...
- 深入浅出ExtJS 第五章 树形结构
5.1 TreePanel的基本使用 //树是一种非常典型的数据结构; 5.1.1 创建一棵树 //树控件有Ext.tree.TreePanel类定义,控件的名称为TreePanel;TreePane ...
- 【blockly教程】第五章 循环结构
在这里,我们将介绍一个新游戏--Pond Tutor 在Pond Tutor(https://blockly-games.appspot.com/pond-tutor)这个游戏中,我们将扮演黄色的鸭子 ...
- C语言 第五章 循环结构练习
一.计算15+16+17 …98+99的和 for实现 #include "stdio.h" void main() { //15+16+17 …98+99 ; ;i<=;i ...
- C语言 第五章 循环结构
一.for 请在屏幕上输出1000个*号 printf("*************************...."); #include "stdio.h" ...
- Java 第五章 循环结构1
循环结构 1 while 循环结构 ,do- while 循环结构 . 循环结构: 必须满足两个条件 . 1,循环条件 和 循环 操作 ! while 循环 特点:先判断,再执行 , 编码规范:缩进, ...
- C 语言入门第五章--循环结构和选择结构
C语言中有三大结构,分别是顺序结构.选择结构和循环结构: 逻辑运算: 与运算: && 或运算:|| 非运算:! ==== #include<stdio.h> int mai ...
- rust结构体
//Rust 并不允许只将某个字段标记为可变 struct User { email: String, name:String, age:i32, sex:String, active:bool, } ...
随机推荐
- flutter issue---->Scaffold.of(context)
当我们想showSnackBar的时候,需要通过Scaffold.of(context)得到Scaffold.但是如果这个context用错的话,flutter就会抛出错误.下面我们通过代码仔细看一下 ...
- 使用 Solon Cloud 的 Jaeger 做请求链路跟踪
<dependency> <groupId>org.noear</groupId> <artifactId>jaeger-solon-cloud-plu ...
- 系统评价——主成分分析PCA的R语言实现(六)
主成分分析(Principal Component Analysis,PCA),是将多个变量通过线性变换以选出较少个数重要变量的一种多元统计分析方法,起到数据约减和集成的作用.在许多领域的研究与应用中 ...
- 内网搭建DNS服务器
DNS:Domain Name Service,域名解析服务 监听端口:udp/53,tcp/53 应用程序:bind 根域:. 一级域: 组织域:.com, .org, .net, .mil, .e ...
- [中间件]Fastjson [转载]
1 Fastjson的安全漏洞 本段摘自: fastjson到底做错了什么?为什么会被频繁爆出漏洞? 前段时间,fastjson被爆出过多次存在漏洞,很多文章报道了这件事儿,并且给出了升级建议. 但是 ...
- CLion在工程中添加目录&新文件
1.将新建文件夹添加到cmake.txt文件里 include_directories(Core/新建文件夹 Core/UserInc Drivers/STM32L4xx_HAL_Driver/Inc ...
- .NET CORE 部署到IIS上,HTTP 错误 500.19 - Internal Server Error
经排查,是因为项目中web.config的rewrite节点不支持,注释掉此节点即可,或者尝试下载相关依赖以支持此节点
- Linux环境变量及其配置
为什么要说这个呢? 本人喜欢使用Linux开发(工作是个硬要求,有些时候不能使用Linux,比如我上一个工作.但是有些时候呢,工作环境比较开放,我可以选择我喜欢的系统进行工作:比如我现在的工作.红红火 ...
- MySQL(九)InnoDB数据结构
InnoDB数据结构 1 数据库的存储结构:页 索引信息和数据记录都是保存在文件上的,确切来说是保存在页结构中:另一方面,索引是在存储引擎上实现的,MySQL服务器上的存储引擎负责对表中数据的读取 ...
- Map集合案例:统计输入多个key值出现的次数
某商店想统计一下一天内所售出的商品以及商品的数量,请编写程序帮助实现,并展示.通过键盘录入商品名称模拟售出的商品, 录入一次表示商品售出一次,直到录入end结束.运行效果如下: 代码: