特征区间

让我们慢下来,先回忆一下目前已经学习过的RUST在面向对象的能力

  • 通过 impl 在类型上 关联函数和方法: 单独使用本身没有什么意义,就和实现一个函数没有区别
  • 支持静态泛型: 函数和类型上支持静态泛型,可以解决一部分代码冗余,尤其在C语言里面(C里面解决这类问题的方法,经常通过void *来实现)
  • 多种形式的特征支持: 特征和泛型组合,可以进一步抽象方法,同时可以作为一种类型特征,表达一个类型是否具有某种特征的能力

OK,我们现在有了特征的能力,也有了泛型的能力,可以写出面向对象的方法了吗?

特征区间作用

trait AnimalSound {
    fn sound(&self);
}

struct Cat;
struct Dog;

impl AnimalSound for Cat {
    fn sound(&self) {
        println!("miao miao");
    }
}

impl AnimalSound for Dog {
    fn sound(&self) {
        println!("wang wang");
    }
}

//主人拥有一个宠物
struct Master<T>{pet:T}

impl<T> Master<T> {

    //主人可以命令宠物发声音
    fn command_sound(&self) {
        let Master{pet} =  self;
        //pet 类型是泛型T,泛型T可以是任何类型  你怎么知道它有没有实现sound方法?
        pet.sound();
    }
}


fn main(){
    let master = Master{pet: Cat };
    master.command_sound();
}

特征区间一个最主要作用 是可以约束 泛型,声明泛型具备某个特征的能力,只有这样,才能在泛型种使用该特征中的方法

没有特征约束的泛型,几乎无法使用,因为根本无法在该泛型上调用任何方法

特征区间声明

特征区间的使用

//在没有使用泛型时,可以声明类型为特征对象
trait AnimalSound {
    fn sound(&self);
}

struct Cat;
struct Dog;

impl AnimalSound for Cat {
    fn sound(&self) {
        println!("miao miao");
    }
}

impl AnimalSound for Dog {
    fn sound(&self) {
        println!("wang wang");
    }
}

fn sound(val: impl AnimalSound)  {
    val.sound();
}

fn main(){    
    sound(Cat);
    sound(Dog);
}

//主人拥有一个宠物
struct Master<T>{pet:T}
//在泛型后增加约束
impl<T: AnimalSound> Master<T> {

    //主人可以命令宠物发声音
    fn command_sound(&self) {
        let Master{pet} =  self;
        //pet 类型是泛型T,泛型T可以是任何类型  你怎么知道它有没有实现sound方法?
        pet.sound();
    }
}


fn main(){
    let master = Master{pet: Cat };
    master.command_sound();
}
//主人拥有一个宠物
struct Master<T>{pet:T}
//使用where子句
impl<T> Master<T>
where T: AnimalSound
{

    //主人可以命令宠物发声音
    fn command_sound(&self) {
        let Master{pet} =  self;
        //pet 类型是泛型T,泛型T可以是任何类型  你怎么知道它有没有实现sound方法?
        pet.sound();
    }
}


fn main(){
    let master = Master{pet: Cat };
    master.command_sound();
}

高级特点

我们已经知道特征可以用来描述 类型应该具有哪些能力,也见到了多种语法,impl语法一般不常用,只会用在类型不太好描述的地方 比如返回一个闭包,我们这里还没有讲过闭包,不过暂前先认为闭包是一个实现了多种 特征的一个类型

//这里先不用关心 闭包的语法,只需要知道 Fn(T) -> U 是一个特征 
fn lazy_adder(a:i32, b:i32) -> impl Fn()->u32 {
    move || a+b
}

fn main(){
    let add_later = lazy_adder(1,2);
    assereq!(3, add_later());
}