参数位置中的 dyn Trait 是什么意思?
What is the meaning of a dyn Trait in argument position?
我可以在return位置看到dyn
和(静态)impl
特征之间的区别,例如:
fn foo() -> Box<dyn Trait> {}
对
fn foo() -> impl Trait {}
在 dyn
版本中,我可以 return 不同的类型,只要它们都实现了 Trait,而在 impl
版本中,我只允许 return 相同类型(如果我 return 引用同样适用)。
但我看不出参数位置 dyn Trait
的用途,例如:
fn foo(x: &dyn Trait) {}
对
fn foo(x: &impl Trait) {} // syntatic sugar of `fn foo<T: Trait>(x: &T){}`
两者有什么区别?我为什么要使用一个或另一个? dyn
版本允许我做什么而静态版本不允许(例如,我不能通过使用 ?Sized
放宽隐式 Sized
限制来做到这一点)?
如果你熟悉C++/Java,那么dyn
对应"interface reference",所以它隐含了动态多态性(因此需要一堆引用的跳转,所以它是有点慢)。
impl
是一个语法糖,为函数定义了一个模板,因此每次您将函数与另一种类型一起使用时,您将获得专门为该类型编译的函数的单独副本。所以没有额外的跳跃,但你的可执行文件会因这些副本而膨胀。 Rust 的思想告诉我们用 <T>
、impl
创建模板,除非编译的版本太多导致可执行文件过于臃肿。
我可以在return位置看到dyn
和(静态)impl
特征之间的区别,例如:
fn foo() -> Box<dyn Trait> {}
对
fn foo() -> impl Trait {}
在 dyn
版本中,我可以 return 不同的类型,只要它们都实现了 Trait,而在 impl
版本中,我只允许 return 相同类型(如果我 return 引用同样适用)。
但我看不出参数位置 dyn Trait
的用途,例如:
fn foo(x: &dyn Trait) {}
对
fn foo(x: &impl Trait) {} // syntatic sugar of `fn foo<T: Trait>(x: &T){}`
两者有什么区别?我为什么要使用一个或另一个? dyn
版本允许我做什么而静态版本不允许(例如,我不能通过使用 ?Sized
放宽隐式 Sized
限制来做到这一点)?
如果你熟悉C++/Java,那么dyn
对应"interface reference",所以它隐含了动态多态性(因此需要一堆引用的跳转,所以它是有点慢)。
impl
是一个语法糖,为函数定义了一个模板,因此每次您将函数与另一种类型一起使用时,您将获得专门为该类型编译的函数的单独副本。所以没有额外的跳跃,但你的可执行文件会因这些副本而膨胀。 Rust 的思想告诉我们用 <T>
、impl
创建模板,除非编译的版本太多导致可执行文件过于臃肿。