首页 > 编程语言 >rust程序设计(3)结构体相关概念和疑问

rust程序设计(3)结构体相关概念和疑问

时间:2023-11-13 23:24:06浏览次数:40  
标签:箱子 GameEventTrait 玩具 User rust 程序设计 结构 Rust 疑问

结构体

// 如何定义结构体
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}
// 如何使用结构体
let user = User {
	active: true,
  username: String::from("someusername123"),
  email: String::from("[email protected]"),
  sign_in_count: 1,
}
// 解构
// 这里有个需要注意的是,如果某个类型没有实现Copy trait
// 那么就会传递所有权,比如这里的email,所以在定义完user2以后,user变量就不能再使用了
// 如果我们额外传入了email,那么user就还能使用
// 另一个问题:结构的位置会影响最后的值吗?就像js的对象结构,我们可以在下面覆盖掉上面解构对象的某些属性
// 在Rust中,结构(destructuring)不是用来“覆盖”值的,而是用来“重组”已存在的值到一个新的变量。这跟JavaScript的对象解构赋值不同,后者允许你在解构的同时覆盖之前对象的属性。
/**
好的,想象一下你有一个玩具箱子,里面有很多玩具。现在你想要一个新的箱子,而且你想把除了最爱的小黄鸭之外的所有玩具都放进新箱子里。在Rust中,我们可以用一个特殊的魔法词“..”,告诉大人我们想这么做。
所以我们对大人说:“请把我的所有玩具,除了小黄鸭,都移到新的箱子里去。”大人就会帮你做这件事。但是一旦玩具移到了新箱子里,你就不能再从旧箱子里拿玩具了,因为它们已经不在那里了。这就像当你把玩具借给朋友后,你就不能再玩那些借出去的玩具了。
而且,你不能像在画画时那样,先画一个太阳,然后又在上面画一个大风筝盖住太阳。在Rust里,一旦你把玩具放到了新箱子,你就决定好了谁去了新箱子,不能改变主意了。
这样的魔法规则帮助确保你的玩具箱子井井有条,每个玩具都知道它应该在哪个箱子里,就像确保你的房间整洁一样。这样你就不会弄丢玩具,也能更容易找到想玩的玩具。
*/
let user2 = User {
	username: String::from("hahaha"),
	...user
}

// rust的整个结构体实例都必须是可变的,才能修改其中的属性,rust不允许只有某些属性是可变的

// build_user 函数返回的User实例,是可变的吗
/**
在Rust中,可变性是由变量的绑定决定的,而不是由函数返回的值决定的。
这意味着,当你的build_user函数返回一个User实例时,它返回的是一个不可变的User实例。
如果你想要修改这个User,你需要在使用它的地方将它绑定到一个可变变量上。
*/
fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username: username,
        email: email,
        sign_in_count: 1,
    }
}

rust的可不可变是针对变量而不是值的吗?

正是如此!在Rust的世界里,可变性(mutability)是关于变量绑定,而不是值本身。想象一下,你的玩具可以放在两种不同的箱子里:一个是用胶带封死的箱子(不可变的),另一个是可以随时打开加东西的箱子(可变的)。玩具(值)本身没变,但根据你放它的箱子的类型,你可能可以改变箱子里的玩具集合。

所以,在Rust中,当你声明一个变量时,你可以选择它是不是mut的,就是选择用哪种箱子。一旦你决定了,只有mut箱子里的玩具(值)才能被换掉或者修改。如果你试图改变一个用胶带封死的箱子里的玩具,Rust会阻止你,确保你不会意外地弄乱你的玩具集合。这个规则是Rust确保程序安全的方式之一,避免了数据在你不知情的情况下被更改。

这样的设计让Rust程序的行为变得非常可预测,并且减少了程序中出现错误的机会。而且,这还帮助Rust管理内存,因为它可以确切地知道何时某个值不再被需要,以及何时它可以被安全地回收或重新使用。

元组结构体

// 注意,Color和Point是不同的类型,即使其中的元素个数和类型一样
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

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

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

没有任何字段的类单元结构体有什么用呢?

好比是小朋友的想象游戏,有时候你会拿个香蕉当电话玩,对吧?虽然它就是个香蕉,但在你的游戏里它就变成了电话。在Rust的世界里,一个没有任何字段的结构体就像是那个香蕉电话,它本身没啥用,但你给它赋予了意义。

就像你可以想象香蕉是电话一样,程序员有时需要一些东西来代表某些特别的事情,即使那个东西本身什么都没有。比如说,我们可能有一个空的结构体来表示游戏中的一个事件,它本身不保存任何信息,但它的存在就代表了某个事件发生了。

还有,就像你玩耍时可能会用一个看不见的"盒子"来装你想象中的宝贝一样,程序员也可能会用这种结构体来做出某些选择。例如,它们可以用来打开或关闭软件的某些功能,就像是开关一样。

另外,这种结构体也像是游戏规则里的“它”,比如“你是它”游戏中的“它”。它代表了一个标记或者一个特定的角色,即使它自己没有任何东西。

所以,即使是空空如也的结构体,在Rust这个大型游戏中也有自己的角色和用途。这就是它们的魔法之处!

让我们来看一个Rust中的代码例子,这个例子里我们将使用一个没有任何字段的结构体来做一些有趣的事情。想象一下,我们有一个游戏,游戏里有一些特殊的时刻,比如“游戏开始”或“游戏结束”。我们可以用不同的结构体来代表这些时刻,哪怕这些结构体里面什么都没有!

这里有一个小小的代码片段:

// 定义一个没有字段的结构体,叫做 `GameEvent`。
struct GameStart; // 游戏开始事件
struct GameEnd; // 游戏结束事件

// 我们可以定义一个函数来处理游戏事件。
// 注意这个函数如何接受不同的事件结构体作为参数。
fn process_game_event(event: impl GameEventTrait) {
    // 在这个函数里,我们可以根据事件的类型来做不同的事情。
    event.print_details();
}

// 让我们为这个结构体实现一个Trait,这个Trait允许我们打印出事件的细节。
trait GameEventTrait {
    fn print_details(&self);
}

// 实现 'GameStart' 结构体的 'GameEventTrait'。
impl GameEventTrait for GameStart {
    fn print_details(&self) {
        println!("The game has started!");
    }
}

// 实现 'GameEnd' 结构体的 'GameEventTrait'。
impl GameEventTrait for GameEnd {
    fn print_details(&self) {
        println!("The game has ended!");
    }
}

// 现在我们可以创建这些事件的实例并处理它们。
let start = GameStart;
let end = GameEnd;

// 处理这些事件
process_game_event(start);
process_game_event(end);

在这个例子中,我们定义了两个没有任何字段的结构体:GameStartGameEnd。它们都实现了一个叫做 GameEventTrait 的trait,这个trait有一个方法 print_details,用于输出一个关于事件的消息。

然后我们有一个 process_game_event 函数,它接受任何实现了 GameEventTrait 的类型的实例。这意味着我们可以传入 GameStartGameEnd 的实例。

当我们调用这个函数并传入 GameStartGameEnd 的实例时,它会打印出相应的开始或结束游戏的消息。

这样的结构体很适合用于事件处理、状态机、消息传递等场景,在这些场景中,标记或者控制流的存在比持有数据更重要。

标签:箱子,GameEventTrait,玩具,User,rust,程序设计,结构,Rust,疑问
From: https://www.cnblogs.com/azoux/p/17830577.html

相关文章

  • C语言程序设计教程3
    1强制类型转换当类型不同时可能导致数据丢失所以需要强制类型转换所以需要强制类型转换,()中间放需要转变的类型2关系操作符>,<,=;>=(大于等于);<=(小于等于);!=(相当于数学里面的“不等于”用于测试不相等);==(用于测试相等),一个=叫做赋值操作符3逻辑操作符&&(逻辑与,”并且“,全真则真,有一......
  • rustbook-ch1-入门指南-总结
    rustbook-ch1-入门指南-总结一、rust版本管理1、安装rust之前需要安装一个C语言编译器。正常编译、执行rust程序,需要一个链接器。由于C语言编译器通常都会附带链接器,所以需要安装一个C语言编译器。除了编译执行需要链接器外,一部分常用的Rust包会依赖使用C语言编写的代码,为了编......
  • Rust语言做数据抓取代码示例
    这个任务需要使用到Rust语言和网络爬虫相关的库,以下是一个简单的示例代码。请注意,由于涉及到的具体问题和数据的复杂性,这个示例可能并不能直接满足你的需求,需要根据你的具体情况进行修改和扩展。usereqwest;useserde::{Deserialize,Serialize};useserde_json::{json,Value};......
  • Rust写的爬虫代码抓取精美的图片
    Rust是一种系统级编程语言,它的设计目标是安全、并发和高效。Rust的爬虫库非常丰富,例如scraper、select、reqwest等等。这些库提供了许多功能,例如HTML解析、HTTP请求、异步处理等等,使得Rust成为一个非常适合编写爬虫的语言。以下是一个使用reqwest和scraper库编写的简单爬虫示例,用于......
  • 实验1:UML与面向对象程序设计原则
    本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、掌握面向对象程序设计中类与类之间的关系以及对应的UML类图;2、理解面向对象程序设计原则。[实验任务一]:UML复习阅读教材第一章复习UML,回答下述问题:Q:面向对象程序设计中类与类的关系都有哪几种?分别用类图实例说明。A......
  • 学期2023-2024-1 20231409 《计算机基础与程序设计》第七周学习总结
    学期2023-2024-120231409《计算机基础与程序设计》第七周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第七周作业这个作业的目标自学教材:数组与链表,基于数组和基于链表实现数据结构,......
  • 2023-2024-1 学号:20231310《计算机基础与程序设计》第7周学习总结
    作业信息这个作业属于哪个课程<班级的链接>https://www.cnblogs.com/rocedu/p/9577842.html#WEEK01这个作业要求在哪里<作业要求的链接>https://edu.cnblogs.com/campus/besti/2022-2023-1-CFAP/homework/12754这个作业的目标<自学教材计算机科学概论第8章并完成......
  • 2023-2024-1 20231425《计算机基础与程序设计》第七周学习总结
    2023-2024-120231425《计算机基础与程序设计》第七周学习总结作业信息所属课程2023-2024-1-计算机基础与程序设计作业要求在哪里2023-2024-1计算机基础与程序设计第六周作业作业目标学习教材《计算机科学概论》第8章《C语言程序设计》第6章并完成云班课......
  • 2023-2024-1 20231427 田泽航 《计算机基础与程序设计》第七周学习总结
    学期(如2023-2024-1)学号(如:20231300)《计算机基础与程序设计》第X周学习总结作业信息这个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2023-2024-1-CFAP/(如2022-2023-1-计算机基础与程序设计)这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.ht......
  • 2023-2024-1 20231318《计算机基础与程序设计》第7周学习总结
    作业信息这个作业属于哪个课程2022-2023-1-计算机基础与程序设计这个作业要求在哪里2022-2023-1计算机基础与程序设计第七周作业这个作业的目标1.学习《计算机科学概论》第8章并完成云班课测试;2.学习《C语言程序设计》第6章并完成云班课测试。作业正文2023-2......