当前位置:   article > 正文

rust笔记10 泛型处理_rust struct 函数指针泛型

rust struct 函数指针泛型

泛型基础

基础的部分直接类比C++的泛型,给出代码实例 :

struct Point<T> {
    x: T,
    y: T
}

impl<T> Point<T> {
    fn foo(&self) -> &Point<T> {
        &self
    }
}

// 模板的特化,只针对f32类型的数据
impl Point<f32> {
    fn add(&self, other: Point<f32>) ->f32 {
        self.x + other.x + self.y + other.y 
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

注意上述代码中,impl后面的T泛型是必须的,这告诉编译器,在Point<T>T是一个泛型标记。

结构体方法中定义的泛型可以和结构体中声明的不一致,比如:

impl<T, U> Point<T, U> {
    fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
        Point {
            x: self.x,
            y: other.y,
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

trait

这就相当于Java的interface,先给出一个代码实例:

pub trait Action {
    // 定义trait
    fn run(&self);
    fn get_name(&self) -> String;
    fn jump(&self) {  // 默认方法
        println!("{} cannot jump", self.get_name());
    }
}

pub struct Car {
    name: String,
}

pub struct Duck {
    name: String,
}

// 为Car结构体实现Action接口
impl Action for Car {
    fn run(&self) {
        println!("car runs");
    }

    fn get_name(&self) -> String {
        self.name.clone()
    }
}

// 为Duck结构体实现Action接口
impl Action for Duck {
    fn run(&self) {
        println!("duck runs");
    }

    fn get_name(&self) -> String {
        self.name.clone()
    }

    fn jump(&self) {
        println!("{} jumps", self.get_name());
    }
}

fn main() {
    let car = Car {
        name: String::from("Ferrari"),
    };
    let duck = Duck {
        name: String::from("Foo"),
    };
    car.run();
    duck.run();
    println!("car name: {}, duck name: {}", car.get_name(), duck.get_name());
    car.jump();
    duck.jump();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

代码输出:

car runs
duck runs
car name: Ferrari, duck name: Foo
Ferrari cannot jump
Foo jumps
  • 1
  • 2
  • 3
  • 4
  • 5

只要实现了trait的所有方法,那么就可以作为trait类型的参数使用,trait中默认实现的方法也包含在内,代码实例:

pub trait Action {
    fn run(&self);
    fn jump(&self);
}

struct Duck {
    name: String,
}

impl Duck {  // 实现自己的方法
    fn get_name(&self) -> String {
        self.name.clone()
    }
}

impl Action for Duck {  // 实现trait的方法
    fn run(&self) {
        println!("{} runs", self.get_name());
    }

    fn jump(&self) {
        println!("{} jumps", self.get_name());
    }
}

// 绝大多数是借用的方式
fn foo(ac: &impl Action) {
    ac.run();
    ac.jump();
}

fn main() {
    let duck = Duck {
        name: String::from("foo"),
    };

    foo(&duck);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

trait bound的概念。我们有泛型函数的概念,但是可以使用trait限制泛型的类型是实现了trait某些方法的泛型,代码实例:

pub trait Action {
    fn run(&self);
    fn jump(&self);
}

pub trait Wealth {
    fn get_money(&self) -> f32;
}

struct Duck {
    name: String,
    money: f32,
}

impl Duck {
    fn get_name(&self) -> String {
        self.name.clone()
    }
}

impl Action for Duck {
    fn run(&self) {
        println!("{} runs", self.get_name());
    }

    fn jump(&self) {
        println!("{} jumps", self.get_name());
    }
}

impl Wealth for Duck {
    fn get_money(&self) -> f32 {
        self.money
    }
}

// 参数必须实现了Action和Wealth这两个trait
fn foo<T: Action + Wealth>(ac: &T) {
    ac.run();
    ac.jump();
    print!("It has {} dollars", ac.get_money());
}

fn main() {
    let duck = Duck {
        name: String::from("foo"),
        money: 8898.4
    };

    foo(&duck);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

如果参数的trait类型过多的话,可以使用where语法,具体的代码实例:

pub trait Action {
    fn run(&self);
}

pub trait Wealth {
    fn pay(&self);
}

pub trait Fame {
    fn show(&self);
}

struct Duck {
    money: f32,
}

struct Human {
    money: f32,
    fame: String,
}

impl Action for Duck {
    fn run(&self) {
        println!("duck runs");
    }
}

impl Wealth for Duck {
    fn pay(&self) {
        println!("duck cost $10");
    }
}

impl Wealth for Human {
    fn pay(&self) {
        println!("human has $10");
    }
}

impl Fame for Human {
    fn show(&self) {
        println!("human has fame");
    }
}

// 利用where进行组合
fn foo<T, U>(man: &T, duck: &U)
    where T: Wealth + Fame,
          U: Action + Wealth
{
    man.pay();
    man.show();
    duck.run();
    duck.pay();
}


fn main() {
    let duck = Duck {
        money: 10.0,
    };

    let man = Human {
        money: 10.0,
        fame: "Dr".to_string(),
    };

    foo(&man, &duck);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

trait也可以作为返回类型,代码实例:

pub trait Action {
    fn run(&self);
}

struct Duck {
    name: String,
}

impl Action for Duck {
    fn run(&self) {
        println!("duck is running");
    }
}

// 返回trait类型
fn foo(name: String) -> impl Action {
    Duck {
        name,
    }
}

fn main() {
    let duck = foo(String::from("foo"));
    duck.run();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

trait实现继承

rust本身没有继承语法,现在利用trait的方式实现继承:

trait Page {
    fn set_page(&self, p: i32) {
        println!("Page Default: 1");
    }
}

trait PerPage {
    fn set_per_page(&self, p: i32) {
        println!("Per Page Default: 10");
    }
}

struct MyPaginate { page: i32 }

impl Page for MyPaginate {}

impl PerPage for MyPaginate {}

trait Paginate: Page + PerPage {  // 这里是继承的语法,Pagninate继承了Page和PerPage
    fn set_skip_page(&self, num: i32) {
        println!("Skip page {:?}", num);
    }
}

impl<T: Page + PerPage> Paginate for T {}  // 这里的意思是为所有实现Page和PerPage的行为实现Paginate特有的方法

fn main() {
    let my_paginate = MyPaginate { page: 10 };
    my_paginate.set_page(10);
    my_paginate.set_per_page(20);
    my_paginate.set_skip_page(10);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号