はじめに
この実験では、Rust における演算子のオーバーロードと、トレイトを通じてそれを実現する方法を探ります。Rust の演算子は、トレイトを使用してオーバーロードできます。これにより、演算子は入力引数に基づいて異なるタスクを実行できます。たとえば、+演算子はaddメソッドのシンタックス・シュガーであり、Addトレイトの実装者によって使用できます。演算子をオーバーロードするトレイト、Addを含めて、core::opsにあります。提供された Rust コードは、カスタム型FooとBarに対して+演算子をオーバーロードする方法を示しており、それぞれ異なる出力型FooBarとBarFooを生成します。
注: 実験でファイル名が指定されていない場合、好きなファイル名を使用できます。たとえば、
main.rsを使用して、rustc main.rs &&./mainでコンパイルして実行できます。
演算子のオーバーロード
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;
// `std::ops::Add` トレイトは、`+` の機能を指定するために使用されます。
// ここでは、`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
}
}
// 型を逆にすることで、非可換な加算を実装します。
// ここでは、`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);
}
まとめ
おめでとうございます!演算子のオーバーロードの実験を完了しました。技術力を向上させるために、LabEx でさらに多くの実験を行って練習してください。