Rust : Trait Object safe 问题

碰到这种情况,代码如下:

#[derive(Clone)]
struct Trade(i32);
trait Bet{
    fn bet(&self);
}
trait Test :Bet
    fn test(&self);
}

impl Test for Trade{
    fn test(&self){}
}

impl Trade{
    fn default(&self) -> Vec>{
        let mut v = Vec::new();
        let trade = Trade(0);
        v.push(Box::new(trade) as Box );
        v
    }
}

这个是没有问题的。

但是,如果把Test改一下:

trait Test :Send
    fn test(&self);
}

但Clone,Sized加上去都会报错。
Rust : Trait Object safe 问题_第1张图片
1、Send+ Sync与Clone、Sized

#[derive(Clone)]
struct Trade(i32);
trait Bet{
    fn bet(&self);
}
trait Test :Send+Sync //而不是Clone和Sized
    fn test(&self);
}

impl Test for Trade{
    fn test(&self){}
}

impl Trade{
    fn default(&self) -> Vec>{
        let mut v = Vec::new();
        let trade = Trade(0);
        v.push(Box::new(trade) as Box );
        v
    }
}

但是,如果是,Sized、Clone组合,仍会报错。

有人解释,加上Clone不是安全的trait。
即object-safe trait.

2、object-safe trait 问题

trait object 它不仅包括指向真实对象的指针,还包括一个指向虚函数表的指针。因此,并不是所有的trait都能作为trait对象使用的。

只有 对象安全(object safe)的 trait 才可以组成 trait 对象。trait的方法满足以下两条要求才是对象安全的:

(1)返回值类型不为 Self
(2)方法没有任何泛型类型参数

Clone是非对象安全的,所以不能作为trait对象。

3、关于trait与泛型,struct结合, 一个更进一步的例子

例子: 有一个Manager,Empylee,他们都共同实现Earn(赚钱的能力) trait。
里面有一个问题:当抽像变成具体时,可能在编译时无法确定对象大小。


pub trait Earn: Send + Sync {
    fn earn(&self);
}

#[derive(Debug, Clone)]
struct Manager
where
    T: Earn,
{
    people: Vec>,
}

trait Run {
    fn run(&self);
}
#[derive(Debug, Clone)]
struct Employee(i32);

impl Earn for Employee {
    fn earn(&self) {}
}

impl Earn for Manager {
    fn earn(&self) {}
}

//
impl Manager {
    fn make_employees(&self) -> Vec> {
        let mut v = Vec::new();
        let e = Employee(0);
        println!("e:{:?}", e);
        v.push(Box::new(e) as Box); // as Box);
        v
    }

    fn make_managers(&self) -> Vec> {
        let mut v = Vec::new();
        {
            // problem :把抽像变具体
            let e = self.make_employees();
            let manager = Manager{ people: e };
        }

        // ok
        let e = Employee(0);
        let manager = Manager {
            people: vec![Box::new(e)],
        };

        v.push(Box::new(manager) as Box);
        v
    }
}
fn main() {
    // let t = Trade(0);
    // let v = t.to_vec();
    println!("ok");
}

关于trait更进一步的了解,可以参考,写得不错:

https://zhuanlan.zhihu.com/p/127365605

4、一个有意思的库: DynClone
在github上,DynClone好象想做些不同的事。

https://github.com/dtolnay/dyn-clone

如:

use dyn_clone::DynClone;

trait MyTrait: DynClone {
    fn recite(&self);
}

impl MyTrait for String {
    fn recite(&self) {
        println!("{} ♫", self);
    }
}

fn main() {
    let line = "The slithy structs did gyre and gimble the namespace";

    // Build a trait object holding a String.
    // This requires String to implement MyTrait and std::clone::Clone.
    let x: Box = Box::new(String::from(line));

    x.recite();

    // The type of x2 is a Box cloned from x.
    let x2 = dyn_clone::clone_box(&*x);

    x2.recite();
}

你可能感兴趣的:(Rust)