Rust 笔记:Rust 语言中的 结构体

简介: 本文先介绍 Rust 语言中的 结构体 的基本用法,然后重点介绍了在 Rust 语言中通过结构体实现面向对象编程的思想、方法并给出了相当多的代码示范。

Rust 笔记Rust 语言中的 结构体


作者李俊才 (jcLee95)https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343

邮箱 :291148484@163.com

本文地址https://blog.csdn.net/qq_28550263/article/details/130876493


【介绍】:本文先介绍 Rust 语言中的 结构体 的基本用法,然后重点介绍了在 Rust 语言中通过结构体实现面向对象编程的思想、方法并给出了相当多的代码示范。

上一节:《 Rust 语言中的 所有权 | 下一节:《 Rust 语言中的枚举


目 录



1. 结构体入门

1.1 什么是结构体

结构体是一种自定义的数据类型,它允许我们将不同类型的数据组合在一起,形成一个新的类型。

1.2 结构体的定义和使用

在Rust中,可以使用struct关键字来定义结构体,并在结构体内部定义其字段。

structPerson {
name: String,
age: u32,
}

上面的代码定义了一个名为Person的结构体,它有两个字段:name和age,分别对应字符串类型和无符号整数类型。

要创建结构体的实例,可以使用以下方式:

letperson1=Person {
name: String::from("Alice"),
age: 25,
};

在上面的示例中,我们创建了一个名为person1的Person结构体实例,并初始化了其字段的值。

1.3 为什么使用结构体

使用结构体可以将相关的数据组合在一起,形成一个有组织的数据结构。结构体可以提供更好的代码组织和可读性,同时还可以为结构体定义方法和实现特定的行为。

1.4 入门示例:定义一个简单的结构体

structPoint {
x: f32,
y: f32,
}

上述代码定义了一个名为Point的结构体,它有两个字段:x和y,类型为f32,即单精度浮点数。

我们可以创建该结构体的实例并访问其字段:

letorigin=Point { x: 0.0, y: 0.0 };
println!("Origin: ({}, {})", origin.x, origin.y);

在上面的示例中,我们创建了一个名为origin的Point结构体实例,并通过.操作符访问了其字段的值。

通过结构体,我们可以方便地组合多个相关字段,形成自定义的数据类型,并使用这些类型的实例进行操作和访问。这样可以提高代码的可读性和可维护性,同时还能更好地组织数据和行为。

2. 结构体中的成员

2.1 成员变量

结构体中的成员变量用于存储不同类型的数据,例如整数、浮点数、字符串等。成员变量可以通过结构体实例的字段名来访问和操作。

structRectangle {
width: u32,
height: u32,
}

上述代码定义了一个名为Rectangle的结构体,它有两个成员变量:width和height,类型为u32,即无符号32位整数。

letrect=Rectangle {
width: 10,
height: 20,
};

在上面的示例中,我们创建了一个名为rect的Rectangle结构体实例,并初始化了其width和height成员变量的值。

println!("Width: {}", rect.width);
println!("Height: {}", rect.height);

通过 . 操作符,我们可以访问结构体实例的成员变量并获取其值。

2.2 成员方法

结构体可以定义成员方法,也称为关联函数。成员方法用于在结构体上执行特定的操作,可以访问结构体的成员变量和其他方法。

implRectangle {
fnarea(&self) ->u32 {
self.width*self.height    }
}

在上述代码中,我们通过impl块为Rectangle结构体实现了一个名为area的方法。该方法用于计算矩形的面积,它获取一个&self参数(即结构体实例的借用),并返回一个u32类型的值。

letrect=Rectangle {
width: 10,
height: 20,
};
println!("Area: {}", rect.area());

在上面的示例中,我们创建了一个名为rect的Rectangle结构体实例,并通过调用area方法计算了其面积。通过.操作符,我们可以在结构体实例上调用方法并获取返回值。

2.3 进阶示例:定义包含变量和方法的结构体

structCircle {
radius: f32,
}
implCircle {
fnnew(radius: f32) ->Circle {
Circle { radius }
    }
fnarea(&self) ->f32 {
3.14*self.radius*self.radius    }
}
fnmain() {
letcircle=Circle::new(5.0);
println!("Area: {}", circle.area());
}

上述示例中,我们定义了一个名为 Circle 的结构体,它有一个成员变量 radius 表示半径。我们还为Circle结构体实现了一个关联函数 new 用于创建实例,并定义了一个成员方法 area 用于计算圆的面积。

在 main 函数中,我们使用 Circle::new 关联函数创建了一个 Circle 结构体实例,并通过调用 area 方法计算了其面积。

通过成员变量和成员方法,结构体提供了一种方便的方式来存储和操作数据。结构体的成员变量可以保存不同类型的数据,成员方法可以对结构体进行特定的操作,使得代码更加清晰和模块化。

3. 结构体的实例化

3.1 创建结构体实例

要创建结构体的实例,可以使用结构体名和初始化成员变量的值。

structCar {
make: String,
model: String,
year: u32,
}

上述代码定义了一个名为Car的结构体,它有三个成员变量:make、model和year,分别对应字符串类型和无符号32位整数类型。

letcar=Car {
make: String::from("Toyota"),
model: String::from("Camry"),
year: 2021,
};

在上面的示例中,我们创建了一个名为car的Car结构体实例,并初始化了其成员变量的值。通过在花括号中提供成员变量名和对应的值,我们可以对结构体进行初始化。

3.2 结构体实例的初始化

我们可以选择只对结构体的部分成员变量进行初始化。在初始化时,未指定的成员变量将使用默认值。

letcar=Car {
make: String::from("Toyota"),
model: String::from("Camry"),
    ..Default::default()
};

在上面的示例中,我们使用了Default trait 中的 default 方法来初始化剩余的成员变量为默认值。

3.3 使用示例:实例化一个结构体并初始化

structPerson {
name: String,
age: u32,
city: String,
}
implPerson {
fnnew(name: String, age: u32, city: String) ->Person {
Person {
name,
age,
city,
        }
    }
}
fnmain() {
letperson1=Person::new(String::from("Alice"), 25, String::from("New York"));
letperson2=Person {
name: String::from("Bob"),
        ..person1    };
println!("Person 1: {}, {}, {}", person1.name, person1.age, person1.city);
println!("Person 2: {}, {}, {}", person2.name, person2.age, person2.city);
}

在上述示例中,我们定义了一个名为Person的结构体,它有三个成员变量:name、age和city。我们为Person结构体实现了一个关联函数new,用于创建实例并初始化其成员变量。

在main函数中,我们使用Person::new关联函数创建了一个名为person1的Person结构体实例。然后,我们使用结构体初始化语法通过person1的值来初始化person2,其中只指定了name字段,其他字段使用person1的对应值。

通过结构体的实例化和初始化,我们可以根据需要创建具有不同属性的结构体实例,并灵活地操作和访问其成员变量。这为我们提供了更多控制和定制化的能力。

4. 结构体的实现

4.1 为结构体实现方法

在Rust中,我们可以为结构体实现方法,使得结构体实例能够执行特定的行为。

structRectangle {
width: u32,
height: u32,
}
implRectangle {
fnarea(&self) ->u32 {
self.width*self.height    }
fnis_square(&self) ->bool {
self.width==self.height    }
}

上述代码定义了一个名为Rectangle的结构体,并为其实现了两个方法:area和is_square。area方法计算矩形的面积,is_square方法判断矩形是否为正方形。

letrect=Rectangle {
width: 10,
height: 20,
};
println!("Area: {}", rect.area());
println!("Is Square: {}", rect.is_square());

在上面的示例中,我们创建了一个名为rect的Rectangle结构体实例,并通过调用area和is_square方法来获取矩形的面积和判断是否为正方形。

通过为结构体实现方法,我们可以将特定的行为与结构体关联起来,使得结构体实例能够直接调用方法来执行相应的操作。

4.2 为结构体实现 trait

除了可以为结构体实现自定义的方法外,我们还可以为结构体实现特定的 trait,从而赋予结构体更多的功能和行为。

structCircle {
radius: f64,
}
traitShape {
fnarea(&self) ->f64;
}
implShapeforCircle {
fnarea(&self) ->f64 {
3.14*self.radius*self.radius    }
}

上述代码定义了一个名为Circle的结构体,并为其实现了Shape trait。Shape trait 包含一个area方法,用于计算形状的面积。

letcircle=Circle { radius: 5.0 };
println!("Area: {}", circle.area());

在上面的示例中,我们创建了一个名为circle的Circle结构体实例,并通过调用area方法来获取圆形的面积。

通过为结构体实现 trait,我们可以将特定的行为和功能抽象出来,并将其应用于不同的结构体上。这样可以实现代码的重用和更好的模块化。

4.3 示例:为结构体实现方法和 trait

structSquare {
side_length: u32,
}
traitShape {
fnarea(&self) ->u32;
fnperimeter(&self) ->u32;
}
implShapeforSquare {
fnarea(&self) ->u32 {
self.side_length*self.side_length    }
fnperimeter(&self) ->u32 {
4*self.side_length    }
}
implSquare {
fnis_square(&self) ->bool {
self.side_length>0 && self.side_length==self.perimeter() /4    }
}
fnmain() {
letsquare=Square { side_length: 5 };
println!("Area: {}", square.area());
println!("Perimeter: {}", square.perimeter());
println!("Is Square: {}", square.is_square());
}

在上述示例中,我们定义了一个名为Square的结构体,并为其实现了Shape trait 和 is_square 方法。Shape trait 包含了计算面积和周长的方法。

在main函数中,我们创建了一个名为square的Square结构体实例,并通过调用area、perimeter和is_square方法来获取正方形的面积、周长以及判断是否为正方形。

通过结构体的方法和 trait 的实现,我们可以扩展结构体的功能,使其具备更多的行为和特性,同时也提高了代码的可读性和可维护性。

5. 结构体与面向对象

5.1 面向对象的特点:抽象、封装、继承、多态

面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,具有以下特点:

  • 抽象(Abstraction):通过将现实世界的对象抽象成类和对象的概念,从而将复杂的问题简化为更易于理解和处理的模块。
  • 封装(Encapsulation):将数据和操作封装在对象中,对象对外部隐藏了内部实现细节,只提供有限的接口与外界进行交互。
  • 继承(Inheritance):通过定义父类和子类之间的关系,子类可以继承父类的属性和方法,从而实现代码的重用和扩展。
  • 多态(Polymorphism):同一种操作可以根据不同对象的类型执行不同的行为,提高代码的灵活性和可扩展性。

5.2 结构体的继承

在Rust中,没有直接的结构体继承机制,但可以通过其他方式实现类似的功能。

5.2.1 tuple 结构体

Tuple 结构体可以被看作是一组没有具名字段的结构体,可以用于表示一组相关的值。

structPerson(String, u32);
fnmain() {
letperson=Person(String::from("Alice"), 25);
println!("Name: {}", person.0);
println!("Age: {}", person.1);
}

在上述示例中,我们定义了一个名为Person的 tuple 结构体,它包含了一个字符串类型和一个无符号32位整数类型。通过索引访问元组的元素,可以获得相应的值。

5.2.2 结构体的嵌套

结构体可以相互嵌套,形成层级关系,从而实现类似继承的效果。

structPerson {
name: String,
age: u32,
}
structEmployee {
person: Person,
employee_id: u32,
}
fnmain() {
letperson=Person {
name: String::from("Alice"),
age: 25,
    };
letemployee=Employee {
person,
employee_id: 12345,
    };
println!("Name: {}", employee.person.name);
println!("Age: {}", employee.person.age);
println!("Employee ID: {}", employee.employee_id);
}

在上面的示例中,我们定义了一个名为Person的结构体和一个名为Employee的结构体。Employee结构体包含了一个Person类型的成员变量person,以及一个employee_id成员变量。

通过结构体的嵌套,我们可以在一个结构体中包含另一个结构体,从而实现类似继承的关系,使得代码更加结构化和模块化。

5.2.3 实战示例:结构体的继承和嵌套

structShape {
color: String,
}
structRectangle {
shape: Shape,
width: u32,
height: u32,
}
structCircle {
shape: Shape,
radius: f64,
}
fnmain() {
letred_rectangle=Rectangle {
shape: Shape {
color: String::from("red"),
        },
width: 10,
height: 20,
    };
letblue_circle=Circle {
shape: Shape {
color: String::from("blue"),
        },
radius: 5.0,
    };
println!("Rectangle: {} x {}", red_rectangle.width, red_rectangle.height);
println!("Circle: radius {}", blue_circle.radius);
println!("Color: Rectangle - {}, Circle - {}", red_rectangle.shape.color, blue_circle.shape.color);
}

在上述示例中,我们定义了一个名为Shape的结构体,以及两个派生结构体Rectangle和Circle。Rectangle和Circle结构体分别嵌套了Shape结构体,从而实现了继承和代码复用的效果。

通过使用结构体的继承和嵌套,我们可以在Rust中模拟实现面向对象编程的特性,使得代码更加灵活和可扩展。

5.3 使用结构体描述对象

结构体可以被用来描述和表示现实世界中的对象,它们可以具有属性(字段)和行为(方法)。

structPerson {
name: String,
age: u32,
}
implPerson {
fnintroduce(&self) {
println!("My name is {} and I am {} years old.", self.name, self.age);
    }
}
fnmain() {
letperson=Person {
name: String::from("Alice"),
age: 25,
    };
person.introduce();
}

在上面的示例中,我们定义了一个名为Person的结构体,它具有name和age两个字段。通过为Person结构体实现introduce方法,我们可以在对象上调用该方法来介绍自己。

在main函数中,我们创建了一个名为person的Person结构体实例,并通过调用introduce方法来打印自我介绍。

通过使用结构体来描述对象,我们可以将对象的属性和行为封装在一起,实现数据和操作的高度内聚性,使得代码更加清晰和可维护。

5.4 与基于类描述对象的对比

Rust中的结构体和面向对象编程中的类有些相似,但也有一些不同之处。本章接下来将从以下几个方面与以 Java 为代表的典型基于类的面向对象编程语言进行对比:

  • 封装性
  • 继承性
  • 多态性
  • 所有权系统

5.4.1 封装性

Rust中的结构体可以使用pub关键字来控制字段和方法的可见性,实现封装。而面向对象的类默认具有公共接口,可以被外部访问。

Rust 语言 面向对象语言如Java
Rust中的结构体可以使用 pub 关键字来控制字段和方法的可见性,从而实现封装。默认情况下,结构体的字段和方法是私有的,只能在同一模块内访问。 面向对象语言如Java:面向对象语言通常使用访问修饰符(如 public、private)来控制类的成员的可见性。类的成员可以被其他类或对象访问。

5.4.2 继承性

Rust中的结构体没有直接的继承机制,但可以通过结构体的嵌套和 trait 的实现来达到类似的效果。

Rust 语言 面向对象语言如Java
Rust中的结构体没有直接的继承机制。然而,可以通过结构体的嵌套和 trait 的实现来实现类似的功能。通过嵌套结构体,可以创建一个结构体,其中包含其他结构体作为其字段。 面向对象语言中的继承允许一个类派生出另一个类,从而实现代码的复用。子类继承了父类的属性和方法,并且可以添加或重写这些成员。

5.4.3 多态性

Rust通过 trait 和泛型来实现多态性,不同类型的结构体可以实现相同的 trait,并以相同的方式进行处理。

Rust 语言 面向对象语言如Java
Rust通过 trait 和泛型来实现多态性。不同类型的结构体可以实现相同的 trait,并以相同的方式进行处理。这使得代码更具灵活性,能够处理不同类型的对象。 面向对象语言使用继承和接口来实现多态性。子类可以替代父类的位置,并以多态的方式使用。

5.4.4 所有权系统

Rust的所有权系统使得在处理对象时更加安全和高效,避免了一些内存管理的问题。

Rust 语言 面向对象语言如Java
Rust的所有权系统确保了内存安全和资源管理。结构体在Rust中是拥有所有权的,当结构体被销毁时,它们的资源也被释放。这种所有权系统使得在处理对象时更加安全和高效。 面向对象语言通常使用垃圾回收或手动内存管理来管理对象的生命周期和内存使用。

6. 总结

本文中我们深入探讨了Rust中的结构体(struct)的概念、用法和实际应用。我们首先介绍了结构体的基本定义和使用,包括如何声明结构体、定义字段和方法,并通过示例代码展示了结构体的基本操作。

接着,我们详细讨论了结构体中的成员,包括成员变量和成员方法。我们介绍了如何在结构体中定义字段和方法,并通过示例演示了如何使用结构体的成员进行操作和访问。

然后,我们讨论了结构体的实例化,包括创建结构体实例和结构体实例的初始化。我们介绍了通过new函数和简化的初始化语法来创建结构体实例,并通过示例代码展示了不同的实例化方式。

接下来,我们探讨了结构体的实现,包括为结构体实现方法和 trait。我们详细介绍了如何为结构体定义方法,并通过示例代码展示了方法的使用。同时,我们讨论了如何为结构体实现 trait,以扩展结构体的功能和行为。

在第五章中,我们与面向对象编程进行了比较,讨论了结构体与面向对象的特点和区别。我们介绍了结构体的继承和嵌套的实现方式,并通过示例代码展示了如何在Rust中模拟实现面向对象的特性。

最后,我们在第六章对全文进行了总结。我们强调了Rust结构体的重要性和实际应用,并指出了结构体在代码设计和开发中的价值。通过使用结构体,我们可以将相关的数据和行为组织在一起,提高代码的可读性、可维护性和灵活性。

目录
相关文章
|
24天前
|
Rust 安全 程序员
开发语言漫谈-rust
if(){}else{}就是C家族的
|
2月前
|
Rust 安全 算法
【深入探索Rust:结构体、枚举与模式匹配】A Deep Dive into Rust: Structs, Enums, and Pattern Matching
【深入探索Rust:结构体、枚举与模式匹配】A Deep Dive into Rust: Structs, Enums, and Pattern Matching
48 0
【深入探索Rust:结构体、枚举与模式匹配】A Deep Dive into Rust: Structs, Enums, and Pattern Matching
|
2月前
|
Rust 监控 数据安全/隐私保护
Rust语言在员工屏幕监控系统中的应用指南
员工屏幕监控系统在现代企业管理中扮演着重要角色。它们能够帮助企业监控员工的活动,确保他们的工作效率和数据安全。在这篇文章中,我们将探讨如何使用Rust语言构建一个简单而高效的员工屏幕监控系统,并提供一些代码示例以帮助你入门。
144 0
|
2月前
|
存储 Rust 开发者
【Rust】——结构体struct
【Rust】——结构体struct
30 0
|
3月前
|
Rust 监控 JavaScript
抖音技术分享:飞鸽IM桌面端基于Rust语言进行重构的技术选型和实践总结
本文将介绍飞鸽IM前端团队如何结合Rust对飞鸽客户端接待能力进行的技术提升,一步步从概念验证、路径分解到分工开发,再到最后上线收益论证,并分享了其中遇到的技术挑战与经验总结等。
62 1
|
3月前
|
Rust 安全 前端开发
Rust还是其他语言:考量因素与案例分析
【2月更文挑战第1天】本文将探讨在选择编程语言时,为什么Rust可能会成为理想的选择。我们将分析Rust的主要优势,如内存安全、性能、并发编程和所有权系统,并将其与其他流行的编程语言进行比较。此外,我们还将通过具体的案例分析,展示Rust在实际应用中的优势和应用场景。
|
3月前
|
Rust 安全 Java
Rust 语言的类型系统
假如让你设计编程语言的类型,你会怎么做? 要定义哪些类型? 类型之间如何交互? 是否需要类型推断? 类型系统是编程语言中用于定义和控制类型的一组规则。
Rust 语言的类型系统
|
3月前
|
Rust 安全
Rust语言中的控制流:条件语句、循环与模式匹配详解
本文将深入探讨Rust编程语言中的控制流构造,包括条件语句、循环和模式匹配。我们将了解如何使用这些工具来构建高效、可读和安全的代码。此外,我们还将探讨Rust在这些构造中提供的一些独特功能和优化。
|
19天前
|
Rust 安全 程序员
|
19天前
|
Rust 安全 程序员
Rust vs Go:解析两者的独特特性和适用场景
在讨论 Rust 与 Go 两种编程语言哪种更优秀时,我们将探讨它们在性能、简易性、安全性、功能、规模和并发处理等方面的比较。同时,我们看看它们有什么共同点和根本的差异。现在就来看看这个友好而公平的对比。