为通用调用者实现特征?
Implement Trait for generic caller?
我刚刚读了 this article about generics and Traits 中的 Rust by Example,他们似乎在通用调用者上实现了一个 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_foo
与 Example
相关联? impl
的范围如何?我可以有板条箱范围的通用实现吗?
How exactly does a generic implementation like this work?
您或多或少可以将泛型视为惰性代码生成:impl<T> Foo for T
表示“对于 every¹ 具体类型 T
,如果需要为 T
实现 Foo
,请使用此函数创建一个。”
How does the compiler know to associate print_foo
with Example
?
当编译器看到方法调用时,这里.print_foo()
,
- 它首先寻找匹配的内在实现,
impl Foo { fn print_foo(&self) {...} }
。在这种情况下找不到。
- 它查看当前范围内可见的所有特征(已定义或
use
d)以查看它们是否定义了一个名为[=14的方法=].
- 它检查
Example
是否实现了这些特征中的任何一个。 Example
实现了 Foo
,因为 所有东西 (未确定大小的类型除外)都实现了 Foo
,因此使用了该特性。
这些规则在 Rust 参考的 Method-call expressions 部分中描述。
How is this impl
scoped? Could I have crate-scoped generic implementations?
特性实现 未限定范围。它们实际上无处不在,无论什么可能被带入当前范围。 (trait implementation coherence 规则旨在确保找到哪些实现永远不会取决于当前 crate 的依赖项中有哪些 crate,即编译器编译了哪些代码。)
然而,traits 是有作用域的:trait 方法永远不会被找到,除非 trait 被 use
引入作用域或者在同一个模块中定义它。
在您的特定情况下,impl<T> Foo for T
意味着 不可能为特征编写任何其他实现 ¹ — 没有“板条箱”之类的东西-范围内的通用实现”。
¹ <T>
并不完全意味着“每种类型”。它的意思是“每个大小类型”,因为大多数通用代码无法处理动态大小/“未大小”类型,如dyn Foo
和[i32]
,所以它是一个有用的默认限制。如果您改写 <T: ?Sized>
,那么泛型确实覆盖了所有可能的类型。
我刚刚读了 this article about generics and Traits 中的 Rust by Example,他们似乎在通用调用者上实现了一个 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_foo
与 Example
相关联? impl
的范围如何?我可以有板条箱范围的通用实现吗?
How exactly does a generic implementation like this work?
您或多或少可以将泛型视为惰性代码生成:impl<T> Foo for T
表示“对于 every¹ 具体类型 T
,如果需要为 T
实现 Foo
,请使用此函数创建一个。”
How does the compiler know to associate
print_foo
withExample
?
当编译器看到方法调用时,这里.print_foo()
,
- 它首先寻找匹配的内在实现,
impl Foo { fn print_foo(&self) {...} }
。在这种情况下找不到。 - 它查看当前范围内可见的所有特征(已定义或
use
d)以查看它们是否定义了一个名为[=14的方法=]. - 它检查
Example
是否实现了这些特征中的任何一个。Example
实现了Foo
,因为 所有东西 (未确定大小的类型除外)都实现了Foo
,因此使用了该特性。
这些规则在 Rust 参考的 Method-call expressions 部分中描述。
How is this
impl
scoped? Could I have crate-scoped generic implementations?
特性实现 未限定范围。它们实际上无处不在,无论什么可能被带入当前范围。 (trait implementation coherence 规则旨在确保找到哪些实现永远不会取决于当前 crate 的依赖项中有哪些 crate,即编译器编译了哪些代码。)
然而,traits 是有作用域的:trait 方法永远不会被找到,除非 trait 被 use
引入作用域或者在同一个模块中定义它。
在您的特定情况下,impl<T> Foo for T
意味着 不可能为特征编写任何其他实现 ¹ — 没有“板条箱”之类的东西-范围内的通用实现”。
¹ <T>
并不完全意味着“每种类型”。它的意思是“每个大小类型”,因为大多数通用代码无法处理动态大小/“未大小”类型,如dyn Foo
和[i32]
,所以它是一个有用的默认限制。如果您改写 <T: ?Sized>
,那么泛型确实覆盖了所有可能的类型。