本文主要是介绍【Rust投稿】捋捋 Rust 中的 impl Trait 和 dyn Trait,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文来自 PrivateRookie 的知乎投稿:https://zhuanlan.zhihu.com/p/109990547
缘起
一切都要从年末换工作碰上特殊时期, 在家闲着无聊又读了几首诗, 突然想写一个可以浏览和背诵诗词的 TUI 程序说起. 我选择了 Cursive 这个 Rust TUI 库. 在实现时有这么一个函数, 它会根据参数的不同返回某个组件(如 Button, TextView 等). 在 Cursive
中, 每个组件都实现了 View
这个 trait, 最初这个函数只会返回某个确定的组件, 所以函数签名可以这样写
fn some_fn(param: SomeType) -> Button
随着开发进度增加, 这个函数需要返回 Button, TextView 等组件中的一个, 我下意识地写出了类似于下面的代码
fn some_fn(param1: i32, param2: i32) -> impl View { if param1 > param2 { // do something...return Button {}; } else { // do something...return TextView {}; }}
可惜 Rust 编译器一如既往地打脸, Rust 编译器报错如下
--> src\main.rs:19:16|
13 | fn some_fn(param1: i32, param2: i32) -> impl View {| --------- expected because this return type...
...
16 | return Button {};| --------- ...is found to be `Button` here
...
19 | return TextView {};| ^^^^^^^^^^^ expected struct `Button`, found struct `TextView`error: aborting due to previous errorFor more information about this error, try `rustc --explain E0308`.
从编译器报错信息看函数返回值虽然是 impl View
但其从 if
分支推断返回值类型为 Button
就不再接受 else
分支返回的 TextView
. 这与 Rust 要求 if else
两个分支的返回值类型相同的特性一致. 那能不能让函数返回多种类型呢? Rust 之所以要求函数不能返回多种类型是因为 Rust 在需要在 编译期确定返回值占用的内存大小, 显然不同类型的返回值其内存大小不一定相同. 既然如此, 把返回值装箱, 返回一个胖指针, 这样我们的返回值大小可以确定了, 这样也许就可以了吧. 尝试把函数修改成如下形式:
fn some_fn(param1: i32, param2: i32) -> Box<View> { if param1 > param2 { // do something...return Box::new(Button {}); } else { // do something...return Box::new(TextView {}); }}
现在代码通过编译了, 但如果使用 Rust 2018, 你会发现编译器会抛出警告:
warning: trait objects without an explicit `dyn` are deprecated--> src\main.rs:13:45|
13 | fn some_fn(param1: i32, param2: i32) -> Box<View> {| ^^^^ help: use `dyn`: `dyn View`|= note: `#[warn(bare_trait_objects)
这篇关于【Rust投稿】捋捋 Rust 中的 impl Trait 和 dyn Trait的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!