我最近开始学习Ruust,并观看了一段关于特征的视频,我了解到如果动态调度,特征也是有效的类型.如果变量的类型具有特征,那么它的代价是

  1. 必须分配堆,而不是分配堆栈
  2. 具有昂贵的初始化成本
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

我试着在谷歌上到处寻找这个模式,但我什么都找不到,我只知道它是is possible,但当涉及到代码性能时,它会带来一些成本,所以我应该在什么时候使用这个模式?

推荐答案

有几个地方需要此模式:

  • 您有一个容器(例如Vec个),其项需要是异类的,但必须具有最低限度的功能才能在容器中使用.例如,软件开发中的典型示例往往是一组不同的回调函数(在RUST中表示为Box<dyn Fn>)或一组不同的图形用户界面小部件.(一个容器只能容纳一种小部件有什么用?)
  • 您正在编写一个特征,其方法需要返回实现某个特征的类型,但实际类型不能命名,这排除了关联类型的使用.在特征上的异步方法中经常会出现这种情况,在TAIT稳定之前,这些方法还不能作为"异步"(或返回impl Future)存在.在此之前,这些特征方法需要返回Box<dyn Future>.

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

Rust相关问答推荐

收集RangeInclusive T到Vec T<><>

Rust中的相互递归特性与默认实现

如何为utoipa中的可选查询参数生成OpenAPI模式?

捕获FnMut闭包的时间不够长

如何高效地将 struct 向量中的字段收集到单独的数组中

Pin<;&;mut可能将Uninit<;T>;>;合并为Pin<;&;mut T>;

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

如何go 除多余的(0..)在迭代中,当它不被使用时?

如何使用Actix Web for Rust高效地为大文件服务

这是什么:`impl Trait for T {}`?

仅发布工作区的二进制 crate

try 从标准输入获取用户名和密码并删除 \r\n

Rust 中指向自身的引用如何工作?

无法将`&Vec>`转换为`&[&str]`

`tokio::pin` 如何改变变量的类型?

切片不能被 `usize` 索引?

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

在 Rust 中退出进程

在 Rust 中组合特征的不同方法是否等效?

为什么 `ref` 会导致此示例*取消引用*一个字段?