为trait object和trait constraint实现

2020-08-11  本文已影响0人  Loru_vest

在Rust里,我们一般倾向于为一个具体的类型实现实现trait,然而,还有一种鲜为人知的写法,为泛型实现trait。分为trait object和带有trait constraint的泛型参数两种。

impl trait for trait object

定义traitX,Y和一个简单的结构体A

trait X {
    fn say_hello(&self);
}

trait Y {
    fn say_yes(&self);
}

struct A(String);

然后可以为trait X object实现traitY

impl Y for dyn X {
    fn say_yes(&self) {
        println!("Yes");
    }
}

要想使用这个say_yes方法,先为A实现traitX

impl X for A {
    fn say_hello(&self) {
        println!("Hello, {}", self.0);
    }
}

然后试试看

fn main() {
    let a: &dyn X = &A("TENX".to_string());
    a.say_yes();
}
$ cargo run                                                                                                                      
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/demo1`
Yes

impl trait for trait constraint

与上面一样,先定义两个traitA,B

trait A {
    fn say_hello();
}

trait B {
    type T;
    fn f() -> Self::T;
}

然后可以为一个带有constraint的泛型参数X实现traitA

impl<X> A for X
where X: B,
      X::T: std::fmt::Display,
{
    fn say_hello() {
        println!("hello, {}", X::f());
    }
}

要使用say_hello,我们先为一个具体的类型实现traitB,注意,associate type必须还满足constraint: std::fmt::Display

struct Foo;

impl B for Foo {
    type T = String;
    fn f() -> String {
        "TENX".to_string()
    }
}

测试一下

fn main() {
    Foo::say_hello();
}
> cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.11s
     Running `target/debug/demo2`
hello, TENX

作用

作用的话?类似于patch?但是为什么不直接在原本的trait里做呢。

上一篇下一篇

猜你喜欢

热点阅读