演算子のオーバーロード

Rustでは、多くの演算子はトレイトによってオーバーロードすることができます。つまり、一部の演算子は引数となる値の型に応じて異なる役割を果たすことができるということです。これが可能なのは、演算子が実際にはメソッド呼び出しの糖衣構文にすぎないからです。例えばa + bにおける+演算子はaddメソッドを(a.add(b)の形で)呼び出します。このaddメソッドはAddトレイトの一部です。それ故、+Addトレイトを実装している全ての型に対して有効なのです。

Addなどの、演算子をオーバーロードするトレイトの一覧はcore::opsにあります。

use std::ops;

struct Foo;
struct Bar;

#[derive(Debug)]
struct FooBar;

#[derive(Debug)]
struct BarFoo;

// The `std::ops::Add` trait is used to specify the functionality of `+`.
// Here, we make `Add<Bar>` - the trait for addition with a RHS of type `Bar`.
// The following block implements the operation: Foo + Bar = FooBar
// `std::ops::Add`トレイトは`+`の振る舞いを規定するために使用される
// ここでは`Foo`に対して`Add<Bar>`を実装する。これは加算時の右辺が`Bar`型
// の時に呼び出されるトレイト。つまり以下は`Foo + Bar = FooBar`という振る舞いを
// もたらす。
impl ops::Add<Bar> for Foo {
    type Output = FooBar;

    fn add(self, _rhs: Bar) -> FooBar {
        println!("> Foo.add(Bar) was called");

        FooBar
    }
}

// By reversing the types, we end up implementing non-commutative addition.
// Here, we make `Add<Foo>` - the trait for addition with a RHS of type `Foo`.
// This block implements the operation: Bar + Foo = BarFoo
// 型を反転することで、非可換の加算を実装できる。ここでは`Bar`に対して
// `Add<Foo>`を実装する。これは加算時の右辺が`Foo`型の時に呼び出されるメソッド。
// つまり以下は`Bar + Foo = BarFoo`という結果をもたらす。
impl ops::Add<Foo> for Bar {
    type Output = BarFoo;

    fn add(self, _rhs: Foo) -> BarFoo {
        println!("> Bar.add(Foo) was called");

        BarFoo
    }
}

fn main() {
    println!("Foo + Bar = {:?}", Foo + Bar);
    println!("Bar + Foo = {:?}", Bar + Foo);
}

See Also

Add, 構文の索引

関連キーワード:  Foo, Add, 関数, メソッド, ops, BarFoo, FooBar, Result, Rust, Example