5.25.通用函数调用语法
最后更新于:2022-04-01 00:44:22
有时,函数可能有相同的名字。就像下面这些代码:
~~~
trait Foo {
fn f(&self);
}
trait Bar {
fn f(&self);
}
struct Baz;
impl Foo for Baz {
fn f(&self) { println!("Baz’s impl of Foo"); }
}
impl Bar for Baz {
fn f(&self) { println!("Baz’s impl of Bar"); }
}
let b = Baz;
~~~
如果我们尝试调用`b.f()`,我们会得到一个错误:
~~~
error: multiple applicable methods in scope [E0034]
b.f();
^~~
note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
`main::Baz`
fn f(&self) { println!("Baz’s impl of Foo"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
`main::Baz`
fn f(&self) { println!("Baz’s impl of Bar"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
我们需要一个区分我们需要调用哪一函数的方法。这个功能叫做“通用函数调用语法”(universal function call syntax),这看起来像这样:
~~~
Foo::f(&b);
Bar::f(&b);
~~~
让我们拆开来看。
~~~
Foo::
Bar::
~~~
调用的这一半是两个traits的类型:`Foo`和`Bar`。这样实际上就区分了这两者:Rust调用你使用的trait里面的方法。
~~~
f(&b)
~~~
当我们使用[方法语法](http://doc.rust-lang.org/nightly/book/method-syntax.html)调用像`b.f()`这样的方法时,如果`f()`需要`&self`,Rust实际上会自动地把`b`借用为`&self`。而在这个例子中,Rust并不会这么做,所以我们需要显式地传递一个`&b`。
## 尖括号形式(Angle-bracket Form)
我们刚才讨论的通用函数调用语法的形式:
~~~
Trait::method(args);
~~~
上面的形式其实是一种缩写。这是在一些情况下需要使用的扩展形式:
~~~
<Type as Trait>::method(args);
~~~
``中。在这个例子中,类型是`Type as Trait`,表示我们想要`method`的`Trait`版本被调用。在没有二义时`as Trait`部分是可选的。尖括号也是一样。因此上面的形式就是一种缩写的形式。
这是一个使用较长形式的例子。
~~~
trait Foo {
fn clone(&self);
}
#[derive(Clone)]
struct Bar;
impl Foo for Bar {
fn clone(&self) {
println!("Making a clone of Bar");
<Bar as Clone>::clone(self);
}
}
~~~
这会调用`Clone`trait的`clone()`方法,而不是`Foo`的。