碰到这种情况,代码如下:
#[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加上去都会报错。
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();
}