微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为通用调用者实现 Trait?

如何解决为通用调用者实现 Trait?

我刚刚阅读了 Rust by Example 中的 this article about generics and Traits,他们似乎在通用调用方上实现了 Trait。查看他们的文章获取完整示例,但这里有一个最小的工作示例:

struct Example;

trait Foo {
  fn print_foo(&self);
}

impl<T> Foo for T {
  fn print_foo(&self) {
    println!("foo");
  }
}

fn main() {
  let example = Example;
  example.print_foo();
}

此示例有效并打印 foo。这是如何运作的?对于上下文,我阅读了完整的 Rust 书,直到前面提到的文章才看到提到这一点。像这样的通用实现究竟是如何工作的?编译器如何知道将 print_fooExample 相关联?这个 impl 的范围如何?我可以使用 crate 范围的通用实现吗?

解决方法

像这样的通用实现究竟是如何工作的?

您可以或多或少地将泛型视为惰性代码生成:impl<T> Foo for T 的意思是“对于 每一个具体类型 T,如果 {{1 }} 对于 Foo 是需要的,使用这个函数创建一个。”

编译器如何知道将 Tprint_foo 相关联?

当编译器看到一个方法调用时,这里Example

  • 它首先寻找匹配的固有实现,.print_foo()。在这种情况下它没有找到。
  • 它查看在当前范围内可见的所有特征(已定义或impl Foo { fn print_foo(&self) {...} }d),以查看它们中是否有任何一个定义了一个名为use的方法。立>
  • 它检查 print_foo 是否实现了这些特征中的任何一个。 Example 实现了 Example,因为一切(除了未调整大小的类型)都实现了 Foo,因此使用了该 trait。

Rust 参考的 Method-call expressions 部分描述了这些规则。

这个 Foo 的范围如何?我可以使用 crate 范围的通用实现吗?

特性实现没有范围。它们有效地存在于任何地方,无论可能将什么带入当前范围。 (trait implementation coherence 规则旨在确保找到哪些实现永远不会取决于当前 crate 的依赖项中的哪些 crate,即编译器编译了哪些代码。)

然而,traits 是有作用域的:除非用 impl 或通过在同一个模块中定义它来将 trait 引入作用域,否则永远不会找到 trait 方法。

在您的特定情况下,use 意味着不可能为该特征编写任何其他实现¹ — 没有“板条箱范围的通用实现”这样的东西.


¹ impl<T> Foo for T 并不是“所有类型”的意思。它的意思是“每个大小类型”,因为大多数通用代码无法处理动态大小/“未大小”的类型,例如 <T>dyn Foo,因此这是一个有用的默认限制.如果您改写 [i32],那么泛型确实涵盖了所有可能的类型。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。