24|类型系统:如何在实战中使用trait object?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了在 Rust 中使用 trait object 进行实战操作的方法和实际应用。通过回顾 trait object 的概念和使用方法,强调了其在灵活性和效率上的折衷。详细讨论了在函数参数和返回值中使用 trait object 的场景,包括使用泛型参数和 trait object 的对比,以及在实际代码中的应用。通过具体的代码示例展示了在参数和返回值中使用 trait object 的实际操作,并介绍了一些实际应用场景。文章还通过性能测试结果展示了使用泛型做静态分发最快,使用 &dyn Executor 和 Box<dyn Executor> 的性能差异,以及对于执行效率低的方法,性能差异的影响。总的来说,大部分情况下,不必太在意 trait object 的性能问题,但在关键路径上需要注意额外的堆内存分配。整体来说,本文通过理论和实践相结合的方式,全面介绍了 trait object 的使用方法和实际应用,对读者快速了解和掌握该技术具有重要参考价值。
《陈天 · Rust 编程第一课》,新⼈⾸单¥68
全部留言(10)
- 最新
- 精选
- Marvichov我自己的机器, 用一个unit type来排除struct initialization带来的cost: ``` struct Dummy(); impl Executor for Dummy { fn run(&self) -> Result<Option<i32>, BoxedError> { Ok(Some(0)) } } ``` generics: 243.34 ps trait object: 2.38 ns boxed object: 3.67ns trait object调用时间是generics的9.78倍...居然差这么多!! 不知道为啥box还是比trait object慢; 按理说, unit type是ZST, 没有大小, 应该不涉及heap memory allocation的...速度应该和trait object一样...但实际测出来还是挺大差距的...
作者回复: 有意思,可能 box 还是没有被完全优化掉?在 ns 的量级,多几条指令可能都会有很大影响。
2021-10-234 - 大汉十三将唉[苦涩] 看不懂了
编辑回复: 不着急,理论不懂可以回到实战里再体会体会,实战不稳可以再去复习复习理论,也欢迎在课程的留言区、微信学习群里和大家交流讨论共同进步。加油~
2023-03-09归属地:云南1 - Bruce有见到trait中,除了关联类型type,还有用const定义的占位符,可以讲讲具体的吗
作者回复: 可以看:https://doc.rust-lang.org/reference/items/associated-items.html#associated-constants。如果你明白了 associate type,那么 associate const 就很好理解。就是类型实现 trait 的时候可以有不同的常量的定义。
2021-11-04 - 罗杰最近在优化 Go 写的即时对战服务,的确堆内存的分配是消耗性能的一大杀手,泛型的消耗相比堆内存的消耗,应该是可以忽略的。但在高频次的调用上,如果可以优化掉不使用泛型,代码理解与维护上没有问题,也还是尽可能避免使用泛型吧。
作者回复: 我的建议是库的代码,尤其是处在核心路径上的库,只要泛型不是太过于干扰可读性,能省内存,能节约 CPU cycle 就尽量节约;应用的代码可以写的省心一些。
2021-10-21 - D. D实现部分需要修改的并不多,把StrategyFn的泛型参数去掉,把reader声明为可变,并在调用函数时传入BufReader的可变引用即可。 我个人觉得修改之后没有带来什么好处,之前的泛型参数并不复杂,而且反而觉得实现时的 Read Write trait bounds让代码读起来很清晰 😂
作者回复: 嗯,是的。
2021-10-20 - A.Y.老师好,我这边想咨询一个问题:如果使用trait object将一个闭包放入了map中,然后需要在其他的线程中取出这个闭包执行,该怎么做呢?最近测试了一下,发现编译器提示错误,好像闭包的 trait object并没有实现Sync2022-05-071
- jimmyWe’ve mentioned that, in Rust, we refrain from calling structs and enums “objects” to distinguish them from other languages’ objects. In a struct or enum, the data in the struct fields and the behavior in impl blocks are separated, whereas in other languages, the data and behavior combined into one concept is often labeled an object. However, trait objects are more like objects in other languages in the sense that they combine data and behavior. But trait objects differ from traditional objects in that we can’t add data to a trait object. Trait objects aren’t as generally useful as objects in other languages: their specific purpose is to allow abstraction across common behavior. --from《The Rust Programming Language》:5. Using Trait Objects That Allow for Values of Different Types2024-02-20归属地:广东
- 阿海二刷课程了,朋友们,有没有Rust岗位推荐呢2023-05-20归属地:广东
- 进击的Lancelot思考题:实现上修改的地方并不多,只需修改 StrategyFn、match_with 和 default_strategy 的函数签名,将其中的泛型参数去除,然后在调用的地方传入相关的引用即可。比较上,rgrep 的泛型参数还是比较简单直观的,代码也并不会很臃肿,这里用 dynamic trait object 来替换没什么必要。 在泛型参数的版本中,传递进来的 BufReader<R> 不需要是可变的,而改用 trait object 就需要使用 &mut dyn BufRead 而不能是 &dyn BufRead? 我尝试将 mut 关键字去掉,在调用 lines 方法时,产生了 “the `lines` method cannot be invoked on a trait object, this has a `Sized` requirement”。我查阅了 rust 文档,BufRead 中 lines 函数的实现为 fn lines(self) -> Lines<Self> where Self: Sized, { Lines { buf: self } } 因此,这里想向老师请教两个问题: 1. 为什么 &mut dyn BufRead 对象能够调用 lines 方法,而 &dyn BufRead 则不行? 2. 根据第十三讲中所说,只有满足对象安全的前提下才能调用 trait object 的方法,而满足对象安全的情况之一,是不允许携带泛型参数,因为 Rust 里带泛型的类型在编译时会做单态化,而 trait object 是运行时的产物,两者不能兼容。那这里的 lines 方法返回值为 Line<Self>,其中 <Self> 应该算是泛型参数吧,那为什么还能调用呢?2022-09-16归属地:广东
- 老实人Honey重新读trait object2022-04-09