结构体
Rust 中的结构体与其他语言中的定义一样,这是一种自定义的数据类型,用来组织多个相关的值,这些被放在结构体里的值就被称为字段(field),当然按以前的习惯还是叫成员变量更顺嘴。Rust 中结构体的成员变量都默认是私有的,想要设为公有可以使用pub关键字。
定义了结构体后,使用它需要为每个字段指定具体值来创建这个实例。创建一个实例时需要以结构体的名字开头,接着在大括号中使用 key: value 键 - 值对的形式提供字段,key 就是成员变量的名字,value 是设置给成员变量的值。
实例中成员变量的顺序不需要和它们在结构体中声明的顺序一致。使用成员变量的方法也和C系一样,使用 . 运算符。如果想要修改结构体中某个成员变量的值,也可以通过 . 取到之后直接赋值,但是,可以修改成员变量的前提是实例对象是可变的也就是创建实例时需要加 mut 关键字,此时整个结构体的所有成员变量都会是可修改的,Rust 中无法单独指定某个或某几个成员变量可变。
参考代码如下:
struct Student
{
name: String,
id: i32,
chinese: i32,
math: i32,
english: i32,
}
fn create_student() -> Student
{
Student {
name: String::from("zhangsan"),
id: 0,
chinese: 30,
math: 20,
english: 10,
}
}
fn main()
{
println!("hello world");
let zs = create_student();
println!("{} 的成绩为 Chinese: {}, Math: {}, English: {}", zs.name, zs.chinese, zs.math, zs.english);
}
这段代码中,我先定义了一个 student 结构体,然后写了一个函数 create_student 返回一个 student 对象; 最后在 main 函数中调用这个函数并输出返回对象的一些成员变量。
我试着让 create_student 返回一个 mut 对象,但是失败了,会有各种错误,然后查了一下,发现似乎在Rust中,方法不能直接返回一个可变对象。因为Rust的设计原则之一是不可变性(Immutability),它鼓励开发者编写安全、并发和高效的代码。如果一个方法返回一个可变对象,那么调用者可能会意外地修改这个对象,从而导致不可预测的行为和潜在的错误。如果要返回可能需要通过 new 的方式,但这部分还没看到,后续看到再补充。
**另外 Rust 的结构体本身不能定义方法,只能通过关联函数的方式为结构体赋予行为!**这也是 Rust 结构体和C++中最大的区别,Rust 的结构体只是一段数据,而不是像C++或者Java中的对象那样的概念。
关联方法的定义首先需要用 impl 关键字指明当前方法所关联的结构体,然后使用 fn + 名称 声明定义,可以拥有参数和返回值, 在同一个 impl 下可以有多个方法。关联方法还可以指定第一个参数为 self,这代表了调用当前方法的结构体实例。例如,给之前的 Student 添加一个计算总分的方法:
struct Student
{
name: String,
id: i32,
chinese: i32,
math: i32,
english: i32,
}
impl Student {
fn total_cores(&self) -> i32 {
self.chinese + self.math + self.english
}
}
fn create_student() -> Student
{
Student {
name: String::from("zhangsan"),
id: 0,
chinese: 30,
math: 20,
english: 10,
}
}
fn main()
{
println!("hello world");
let zs = create_student();
println!("{} 的成绩为 Chinese: {}, Math: {}, English: {}", zs.name, zs.chinese, zs.math, zs.english);
println!("总成绩为: {}", zs.total_cores());
}
最终输出结果为:
impl 下定义的方法的第一个参数也可以不是 self,但是这样这个方法便不是与当前结构体关联的了,和一个普通定义的函数没区别。不过这种关联函数经常被用作返回一个结构体新实例的构造函数,这种函数的名称也通常为 new ,不过 new 并不是一个关键字。这样就可以将刚才的 create_student 封装进 impl 里面了, 并且返回值类型可以直接写为 self 。
另外定义的方法还可以与成员变量同名,当一个结构体存在同名的成员变量与方法时编译器在检测时如果在调用这个名的后面加上括号时,就认为调用的是方法,当未加括号则认为调用的是成员变量。当前Rust开发中大多数情况下与字段同名的方法都将被定义为只返回字段中的值,而不做其他事情。一般这样的方法在其他语言中被定义为 get ,主要作用就是保持成员变量的私密性。代码示例:
struct Student
{
name: String,
id: i32,
chinese: i32,
math: i32,
english: i32,
}
impl Student {
fn total_cores(&self) -> i32 {
self.chinese + self.math + self.english
}
fn create_student() -> Self
{
Student {
name: String::from("zhangsan"),
id: 0,
chinese: 30,
math: 20,
english: 10,
}
}
fn chinese(&self) -> i32 {
return self.chinese;
}
}
fn main()
{
println!("hello world");
let zs = Student::create_student();
println!("{} 的成绩为 Chinese: {}, Math: {}, English: {}", zs.name, zs.chinese(), zs.math, zs.english);
println!("总成绩为: {}", zs.total_cores());
}