Rust 将 T、&T 和 &mut T 视为单独的类型。作为单独的类型,我们可以为它们中的每一个实现不同的方法。示例:
struct Struct;
trait Printable {
fn print(self);
}
impl Printable for Struct {
fn print(self) {
println!("I'm an owned Struct");
}
}
impl Printable for &Struct {
fn print(self) {
println!("I'm a Struct reference");
}
}
fn main() {
let s = Struct;
let s_ref = &Struct;
s.print();
s_ref.print();
}
如果我们对得到的 trait 方法进行脱糖:
fn print(self: Self) { /* implementation */ }
其中Self 等于实现类型,在Struct 的情况下为:
fn print(self: Struct) { /* implementation */ }
在&Struct的情况下是:
fn print(self: &Struct) { /* implementation */ }
所以真的self 可以是拥有的类型或不可变引用或可变引用。您可以在对Iterators 的可变引用上调用take 的原因是because of this generic blanket impl which implements the Iterator trait on all mutable references to Iterators:
impl<'_, I> Iterator for &'_ mut I where I: Iterator + ?Sized { /* implementation */ }
让我们以vec.into_iter() 为例。由于它返回实现了Iterator 的std::vec::IntoIter,我们知道take 的这个实现必须存在:
take(self: std::vec::IntoIter, n: usize) -> Take<std::vec::IntoIter> { /* implementation */ }
然而,我们也知道take 的&mut std::vec::IntoIter 的实现必须存在,因为它将由上面提到的通用毯子impl 自动生成,并且该实现的签名如下所示:
take(self: &mut std::vec::IntoIter, n: usize) -> Take<&mut std::vec::IntoIter> { /* implementation */ }
这就是为什么您可以在对实现Iterator 的任何类型的任何可变引用上调用take。