gpt4 book ai didi

syntax - 为什么将特征作为函数参数传递时需要 `impl`?

转载 作者:行者123 更新时间:2023-11-29 08:26:11 28 4
gpt4 key购买 nike

在下面传递一个trait作为参数的例子中,在函数签名中发送impl需要什么?

我知道 traits 是更通用的类型而不是具体类型,但是由于 Rust 编译器不允许跨结构和 traits 共享名称,为什么需要在函数中提供 impl签名来表示类型?

pub fn notify(item: impl Summary) {
println!("Breaking news! {}", item.summarize());
}

文档提到上面的签名只是下面签名的语法糖。使用 trait Summary 而不是 impl Summary 是否有意义,因为 impl 也可用于在结构上定义方法?

pub fn notify<T: Summary>(item: T) {
println!("Breaking news! {}", item.summarize());
}

是否有任何我遗漏的隐藏概念?

最佳答案

与 Go 或 Java 等语言相反,Rust 允许静态和动态调度,并且需要一些语法让程序员在两者之间进行选择。

因为动态调度必须对可能不是 Sized 的对象起作用,您需要引用才能使用它。也就是说,您将使用 &dyn TraitBox<dyn Trait> (注意:由于历史原因,dyn 关键字不是必需的,但现代 Rust 使用它)。在 C++ 中,动态调度也需要引用或指针。

静态分派(dispatch)不是 Go 或 Java 所拥有的。在 C++ 中,它与模板和鸭子类型一起使用。在 Rust 中,它适用于泛型和特征,其原始语法是:

fn some_function<T: Trait>(foo: T) { … }

后来,在该语言中添加了以下语法:

fn some_function(foo: impl Trait) { … }

等同于上面的

这种语法最初是为了在返回类型中使用而发明的,那里没有通用的等价物:

fn some_function() -> impl Trait { … }

这意味着some_function可以返回任何实现 Trait 的单一类型, 但这种类型必须在编译时已知。这比返回 Box<Trait> 有一些性能优势例如。在 C++ 中,最接近的等价物将返回 autodecltype(auto) .

为对称添加了参数位置的语法。

您可能想知道为什么不简单地使泛型隐式并具有:

fn some_function(foo: Trait) { … }

但这会有点困惑。 Trait本身没有大小,因此不能用作参数,除非它们是通用的。这将使特征在未确定大小的类型领域中脱颖而出。例如,如果 (foo: Trait)会工作,你可能想知道为什么 (foo: str)没有,但是那是什么意思?使泛型隐式化还存在其他问题,例如,特征中的泛型使特征成为非对象安全的。


稍后,Rust 可能会扩展这些存在类型并在模块级别允许这样做:

type Foo = impl Bar;

(目前允许在夜间使用,由 type_alias_impl_trait 特性保护)


最后,您问的是为什么语法是 impl Foo , 而不是 trait Foo .这读起来就像“实现 Foo 的类型”。 original RFC没有太多讨论替代语法。 Another RFC discusses the syntax more ,特别是语法是否应该是 any Foo在参数位置,和some Foo在返回位置。语法 trait Foo据我所知,从未考虑过。

关于syntax - 为什么将特征作为函数参数传递时需要 `impl`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57562632/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com