什么时候我应该在rust中使用一个trait作为类型?

wnrlj8wa  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(172)

我最近开始学习rust,并观看了一个关于traits的视频,我了解到如果动态分派,traits也是有效的类型。如果一个变量的trait的代价是
1.必须是堆分配的,而不是堆栈分配的
1.具有昂贵的初始化成本

struct Animal;

trait Roars {
    fn roar(&self);
}

//implement trait roar
impl Roars for Animal {
    fn roar(&self) {
        println!("roarrrrrr")
    }
}

//implement a method rawr
impl Animal {
    fn rawr(&self) {
        println!("rawrrrrrrrrr")
    }
}

fn main() {
    let lion: Box<dyn Roars> = Box::new(Animal);
    let cheeta: Animal = Animal;
    lion.roar();
    cheeta.rawr()
}

>>>roarrrrrr
>>>rawrrrrrrrrr

我试着在google上到处寻找这个模式什么时候是个好主意,但是我找不到任何东西,我只知道它是可能的,但是当涉及到代码性能时,它会有一点代价,所以我应该什么时候使用这个模式?

zkure5ic

zkure5ic1#

有几个地方需要这种模式:

  • 您有一个容器(例如Vec),其项需要是异构的,但必须具有在容器中有用的最小功能。例如,软件开发中的规范示例往往是一组异构的回调函数(在Rust中表示为Box<dyn Fn>)或一组异构的GUI小部件。(一个只能容纳一种小部件的容器有什么用?)
  • 您正在编写一个trait,其中一个方法需要返回一个实现某个trait的类型,但实际类型无法命名,这排除了使用关联类型。traits上的异步方法经常会出现这种情况,在TAIT稳定之前,traits还不能以“async”(或返回impl Future)的形式存在。在此之前,这些trait方法需要返回Box<dyn Future>

在其他地方,这种模式可以大大简化代码。使用dyn擦除类型通常可以消除泛型类型参数,有时简化代码值得额外的堆分配,vtable查找和间接数据的相当小的运行时成本。

相关问题