Rust泛型特征、集合类型
目录
- 泛型与特征
- 泛型Generics
- 特征Trait
- 特征对象
- 进一步深入特征
- 集合类型
- 动态数组Vector
- KV存储HashMap
泛型与特征
泛型 (Generics)
基础概念
- 定义:泛型允许我们编写可以处理多种类型的代码。
- 语法:使用尖括号<>来指定类型参数。
fn identity<T>(arg: T) -> T {
arg
}
fn main() {
let output = identity(String::from("Hello World"));
println!("The output is: {}", output);
}
在这个例子中,identity
函数接受一个类型参数T,这意味着它可以接受任何类型的输入,并返回相同类型的值。
使用约束
- 添加约束:可以为类型参数添加约束,确保其满足某些条件。
- 示例:要求类型必须实现某个特定的trait。
trait ExampleTrait {
fn example_method(&self);
}
struct ExampleStruct;
impl ExampleTrait for ExampleStruct {
fn example_method(&self) {
println!("Example method called");
}
}
fn requires_example_trait<T: ExampleTrait>(t: T) {
t.example_method();
}
fn main() {
let example = ExampleStruct;
requires_example_trait(example);
}
特征 (Traits)
定义
- 定义:特征定义了一组方法签名,描述了某种行为。
- 语法:使用trait关键字定义。
trait Summary {
fn summarize(&self) -> String;
}
struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
fn notify(item: &impl Summary) {
println!("Breaking news: {}", item.summarize());
}
fn main() {
let article = NewsArticle {
headline: String::from("Penguins win the Stanley Cup Championship!"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from(
"The Pittsburgh Penguins once again are the best \
hockey team in NHL.",
),
};
notify(&article);
}
特征对象
- 定义:允许我们拥有不确定具体类型的对象。
- 语法:使用
&dyn TraitName
形式。
trait Animal {
fn make_sound(&self);
}
struct Dog;
impl Animal for Dog {
fn make_sound(&self) {
println!("Woof!");
}
}
struct Cat;
impl Animal for Cat {
fn make_sound(&self) {
println!("Meow!");
}
}
fn animal_sound(animal: &dyn Animal) {
animal.make_sound();
}
fn main() {
let dog = Dog;
let cat = Cat;
animal_sound(&dog);
animal_sound(&cat);
}
进一步深入特征
默认实现
- 默认方法:可以在
trait
定义时提供默认实现。
trait Draw {
fn draw(&self);
fn default_draw(&self) {
println!("Default drawing behavior");
}
}
struct Screen;
impl Draw for Screen {
fn draw(&self) {
println!("Drawing Screen");
}
}
fn main() {
let screen = Screen;
screen.draw();
screen.default_draw();
}
高阶trait
- 高阶trait:trait可以要求其实现者也实现其他trait。
trait Display: std::fmt::Display {}
impl<T: std::fmt::Display> Display for T {}
fn display<T: Display>(t: T) {
println!("{}", t);
}
fn main() {
display(42);
display(String::from("Hello, world!"));
}
协变与逆变(Covariance and Contravariance)
协变
- 定义:如果类型 A 是类型 B 的子类型,那么
Vec<A>
也是Vec<B>
的子类型。 - 语法:使用
?Sized
或者+
操作符。
trait Animal {
fn make_sound(&self);
}
struct Dog;
impl Animal for Dog {
fn make_sound(&self) {
println!("Woof!");
}
}
struct Cat;
impl Animal for Cat {
fn make_sound(&self) {
println!("Meow!");
}
}
// 协变示例
fn print_animals(animals: &[&dyn Animal]) {
for animal in animals {
animal.make_sound();
}
}
fn main() {
let dogs = vec![&Dog {}, &Dog {}];
let cats = vec![&Cat {}, &Cat {}];
print_animals(&dogs);
print_animals(&cats);
}
逆变
- 定义:如果类型 A 是类型 B 的子类型,那么
Fn(A)
是Fn(B)
的子类型。 - 语法:使用
+
操作符。
// 逆变示例
fn apply<F, T>(func: F, value: T) -> T
where
F: Fn(T) -> T,
{
func(value)
}
fn double(x: isize) -> isize {
x * 2
}
fn main() {
let result = apply(double, 5);
println!("Result: {}", result);
}
集合类型
动态数组 Vector
基本使用 Vector 是一个动态大小的数组,它支持在运行时添加和移除元素。Vector 的元素必须是同一种类型。
创建Vector
let v: Vec<i32> = Vec::new(); // 创建一个空的 i32 类型的 Vector
let mut v = vec![1, 2, 3]; // 创建并初始化一个包含三个元素的 Vector
向 Vector 添加元素
v.push(4); // 向末尾添加一个元素
访问 Vector 元素
let third: Option<&i32> = v.get(2); // 获取第三个元素的引用
println!("The third element is {:?}", third);
let third: &i32 = &v[2]; // 直接获取第三个元素,如果越界会导致 panic!
println!("The third element is {}", third);
遍历 Vector
for i in &v {
println!("{}", i);
}
for i in &mut v {
*i += 50; // 修改 Vector 中的元素
}
移除 Vector 元素
let last = v.pop(); // 移除并返回最后一个元素
进阶使用
- 迭代器:
Vector
支持多种迭代方式。 - 枚举:可以使用
enumerate
方法获取元素及其索引。 - 链式调用:可以使用
.iter()
和.map()
等方法来操作Vector
。
KV 存储 HashMap
基本使用
HashMap 是一种基于哈希表实现的键值对存储结构,它提供了快速的插入和查找操作。
创建 HashMap
use std::collections::HashMap;
let mut scores = HashMap::new(); // 创建一个空的 HashMap
插入键值对
scores.insert(String::from("Blue"), 10); // 插入一个新的键值对
访问 HashMap 中的值
let team_name = String::from("Blue");
let score = scores.get(&team_name); // 获取值,返回 Option<&V>
更新或插入
scores.entry(team_name).or_insert(0); // 如果键不存在,则插入默认值
遍历 HashMap
for (key, value) in &scores {
println!("{}: {}", key, value);
}
进阶使用
- 模式匹配:可以使用模式匹配来处理 Option 和 Result 类型。
- 默认值:使用 get 或 entry API 来安全地处理缺失的键。
- 移除元素:使用
remove
方法来移除键值对。
Vector 示例
fn main() {
let mut numbers = Vec::new();
numbers.push(1);
numbers.push(2);
numbers.push(3);
for (index, value) in numbers.iter().enumerate() {
println!("Element at index {}: {}", index, value);
}
if let Some(third) = numbers.get(2) {
println!("The third element is {}", third);
}
}
HashMap 示例
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let team_name = String::from("Blue");
let score = scores.get(&team_name);
match score {
Some(&value) => println!("Score of {}: {}", team_name, value),
None => println!("No score for {}", team_name),
}
for (key, value) in &scores {
println!("{}: {}", key, value);
}
}
版权声明
本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。