man*_*nth 6 syntax traits rust
在以下将特征作为参数传递的示例中,需要发送impl
函数签名吗?
我知道特征是更通用的类型而不是具体类型,但由于 Rust 编译器不允许跨结构和特征共享名称,为什么需要impl
在函数签名中提供来表示类型?
pub fn notify(item: impl Summary) {
println!("Breaking news! {}", item.summarize());
}
Run Code Online (Sandbox Code Playgroud)
文档提到上面的签名只是下面签名的语法糖。trait Summary
使用 as代替impl Summary
asimpl
也可以用来定义结构体上的方法不是有意义吗?
pub fn notify<T: Summary>(item: T) {
println!("Breaking news! {}", item.summarize());
}
Run Code Online (Sandbox Code Playgroud)
我错过了它周围的任何隐藏概念吗?
mca*_*ton 18
与 Go 或 Java 等语言相反,Rust 允许静态和动态分派,并且需要一些语法来让程序员在两者之间进行选择。
\n\n由于动态调度必须适用于可能不适用的对象Sized
,因此您需要一个引用才能使用它。也就是说,您可以使用&dyn Trait
or Box<dyn Trait>
(注意:由于历史原因,dyn
关键字不是必需的,但现代 Rust 使用它)。在 C++ 中,动态调度还需要引用或指针。
Go 或 Java 没有静态调度。在 C++ 中,它与模板和鸭子类型一起使用。在 Rust 中,它与泛型和特征一起使用,其原始语法是:
\n\nfn some_function<T: Trait>(foo: T) { \xe2\x80\xa6 }\n
Run Code Online (Sandbox Code Playgroud)\n\n后来,以下语法被添加到该语言中:
\n\nfn some_function(foo: impl Trait) { \xe2\x80\xa6 }\n
Run Code Online (Sandbox Code Playgroud)\n\n这相当于上面的。
\n\n这种语法最初是为了在返回类型中使用而发明的,其中没有通用的等效项:
\n\nfn some_function() -> impl Trait { \xe2\x80\xa6 }\n
Run Code Online (Sandbox Code Playgroud)\n\n这意味着some_function
可以返回实现 的任何单一类型Trait
,但该类型必须在编译时已知。Box<Trait>
例如,与返回相比,这具有一些性能优势。在 C++ 中,最接近的等效项是返回auto
or decltype(auto)
。
添加参数位置中的语法是为了对称。
\n\n您可能想知道为什么不简单地使泛型隐式并具有:
\n\nfn some_function(foo: Trait) { \xe2\x80\xa6 }\n
Run Code Online (Sandbox Code Playgroud)\n\n但这会有点令人困惑。Trait
其本身没有大小,因此不能用作参数,除非它们是通用的。这将使特征在无尺寸类型领域中脱颖而出。例如,如果(foo: Trait)
可行,您可能想知道为什么(foo: str)
不行,但这意味着什么?隐式泛型还存在其他问题,例如特征中的泛型使特征变得非对象安全。
稍后,Rust 可能会扩展这些存在类型并在模块级别允许这样做:
\n\nfn some_function(foo: impl Trait) { \xe2\x80\xa6 }\n
Run Code Online (Sandbox Code Playgroud)\n\n(目前每晚允许,由该type_alias_impl_trait
功能保护)
最后,您问为什么语法是impl Foo
,而不是trait Foo
. 这读起来很好“一种实现 Foo 的类型”。原始RFC没有过多讨论替代语法。另一个 RFC 更多地讨论了语法,特别是语法是否应该位于any Foo
参数位置和some Foo
返回位置。trait Foo
据我所知,从未考虑过语法。
归档时间: |
|
查看次数: |
5478 次 |
最近记录: |