Rust : Trait Object safe 问题

tech2024-12-21  0

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

#[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<Box<dyn Test>>{ let mut v = Vec::new(); let trade = Trade(0); v.push(Box::new(trade) as Box<dyn Test > ); v } }

这个是没有问题的。

但是,如果把Test改一下:

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

但Clone,Sized加上去都会报错。 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<Box<dyn Test>>{ let mut v = Vec::new(); let trade = Trade(0); v.push(Box::new(trade) as Box<dyn Test > ); 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<T> where T: Earn, { people: Vec<Box<T>>, } trait Run { fn run(&self); } #[derive(Debug, Clone)] struct Employee(i32); impl Earn for Employee { fn earn(&self) {} } impl<T: Earn> Earn for Manager<T> { fn earn(&self) {} } // impl<T: Earn> Manager<T> { fn make_employees(&self) -> Vec<Box<dyn Earn>> { let mut v = Vec::new(); let e = Employee(0); println!("e:{:?}", e); v.push(Box::new(e) as Box<dyn Earn>); // as Box<dyn Earn>); v } fn make_managers(&self) -> Vec<Box<dyn Earn>> { 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<dyn Earn>); 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<dyn MyTrait> = Box::new(String::from(line)); x.recite(); // The type of x2 is a Box<dyn MyTrait> cloned from x. let x2 = dyn_clone::clone_box(&*x); x2.recite(); }
最新回复(0)