Learning Rust - Universal Function Call Syntax

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;
}

FooBarというtraitがともにf()メソッドをもっていて、 それらをBazstructにimplしました。 これだけではエラーにはなりませんが、b.f()を呼ぶとエラーです。

b.f(); // Error

これはシグネチャが違っていても(Barf()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)でも大丈夫なようです。 どっちでもいいということでしょうか。