注意: 最新版のドキュメントをご覧ください。この第1版ドキュメントは古くなっており、最新情報が反映されていません。リンク先のドキュメントが現在の Rust の最新のドキュメントです。
Rustは制限された形式での演算子オーバーロードを提供しており、オーバーロード可能な演算子がいくつか存在します。 型同士の間の演算子をサポートするためのトレイトが存在し、それらを実装することで演算子をオーバーロードすることができます。
例えば、 +
の演算子は Add
トレイトを利用することでオーバーロードすることができます:
use std::ops::Add; #[derive(Debug)] struct Point { x: i32, y: i32, } impl Add for Point { type Output = Point; fn add(self, other: Point) -> Point { Point { x: self.x + other.x, y: self.y + other.y } } } fn main() { let p1 = Point { x: 1, y: 0 }; let p2 = Point { x: 2, y: 3 }; let p3 = p1 + p2; println!("{:?}", p3); }
main
中で、2つの Point
に対して +
を使うことができます、
これは Point
に対して Add<Output=Point>
を実装したためです。
同じ方法でオーバーロード可能な演算子が多数あります、
それらに対応したトレイトは std::ops
モジュール内に存在します。
全てのオーバーロード可能な演算子と対応するトレイトについては std::ops
のドキュメントを読んで確認して下さい。
それらのトレイトの実装はパターンに従います。 Add
トレイトを詳しく見ていきましょう:
pub trait Add<RHS = Self> { type Output; fn add(self, rhs: RHS) -> Self::Output; }
関連する3つの型が存在します: impl Add
を実装するもの、 デフォルトが Self
の RHS
、 そして Output
。
例えば、式 let z = x + y
においては x
は Self
型 y
は RHS、 z
は Self::Output
型となります。
impl Add<i32> for Point { type Output = f64; fn add(self, rhs: i32) -> f64 { // i32をPointに加算しf64を返す } }
上のコードによって以下の様に書けるようになります:
fn main() { let p: Point = // ... let x: f64 = p + 2i32; }let p: Point = // ... let x: f64 = p + 2i32;
オペレータトレイトがどのように定義されているかについて学びましたので、
トレイトについての章 の HasArea
トレイトと Square
構造体をさらに一般的に定義することができます:
use std::ops::Mul; trait HasArea<T> { fn area(&self) -> T; } struct Square<T> { x: T, y: T, side: T, } impl<T> HasArea<T> for Square<T> where T: Mul<Output=T> + Copy { fn area(&self) -> T { self.side * self.side } } fn main() { let s = Square { x: 0.0f64, y: 0.0f64, side: 12.0f64, }; println!("Area of s: {}", s.area()); }
HasArea
と Square
について、型パラメータ T
を宣言し f64
で置換しました。
impl
はさらに関連するモディフィケーションを必要とします:
impl<T> HasArea<T> for Square<T> where T: Mul<Output=T> + Copy { ... }
area
メソッドは辺を掛けることが可能なことを必要としています。
そのため型 T
が std::ops::Mul
を実装していなければならないと宣言しています。
上で説明した Add
と同様に、Mul
は Output
パラメータを取ります: 数値を掛け算した時に型が変わらないことを知っていますので、 Output
も T
と設定します。
また T
は、Rustが self.side
を返り値にムーブするのを試みないようにコピーをサポートしている必要があります。