Syntax and Semantics
Universal Function Call Syntax
別々のtraitが同名の関数を持っていることがありますね。
fn main() {
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;
}
Foo
とBar
というtraitがともにf()
メソッドをもっていて、
それらをBaz
structにimplしました。
これだけではエラーにはなりませんが、b.f()
を呼ぶとエラーです。
b.f(); // Error
これはシグネチャが違っていても(Bar
のf()
がf(&self, i32)
とかでも)、
コンパイルエラーになるようです。
それで、どうにかして曖昧さをなくさないといけないのですが、 ‘universal function call syntax’を使えば可能です。
Syntaxは以下のように、
Foo::f(&b);
Bar::f(&b);
C++の名前空間みたいにtraitを指定します。
b.f()
のようなメソッド呼び出しとは違い、&b
は明示的に渡さなければいけません。
Angle-bracket Form
実はこの’universal function call syntax’は、 ‘Angle-bracket form’の短縮版らしいです。 Angle-bracket formは、
<Type as Trait>::method(args);
のようなsyntaxで記述します。
Type
にimplされているTrait
がもつmethod
を呼ぶ、ということですね。
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::clone(self)
でも大丈夫なようです。
どっちでもいいということでしょうか。