Rust泛型特征、集合类型

目录泛型与特征泛型Generics特征Trait特征对象进一步深入特征集合类型动态数组VectorKV存储HashMap泛型与特征泛型(Generics)基础概念定义:泛型允许我们编写可以处理多种类型的代码。语法:使用尖括号<>来指定类型参数。fn

目录


泛型与特征

泛型 (Generics)

基础概念

  • 定义:泛型允许我们编写可以处理多种类型的代码。
  • 语法:使用尖括号<>来指定类型参数。
fn identity&lt;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&lt;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&lt;T: std::fmt::Display> Display for T {}

fn display&lt;T: Display>(t: T) {
    println!("{}", t);
}

fn main() {
    display(42);
    display(String::from("Hello, world!"));
}

协变与逆变(Covariance and Contravariance)

协变

  • 定义:如果类型 A 是类型 B 的子类型,那么 Vec&lt;A> 也是 Vec&lt;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&lt;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&lt;i32> = Vec::new(); // 创建一个空的 i32 类型的 Vector
let mut v = vec![1, 2, 3];    // 创建并初始化一个包含三个元素的 Vector

向 Vector 添加元素

v.push(4); // 向末尾添加一个元素

访问 Vector 元素

let third: Option&lt;&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&lt;&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);
    }
}
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
天涯学馆
天涯学馆
0x9d6d...50d5
资深大厂程序员,12年开发经验,致力于探索前沿技术!