https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/traits.html
https://doc.rust-jp.rs/rust-by-example-ja/trait/derive.html
このドキュメントを見てもよくわからなかったので自分なりにキホンがわかるように。
まずざっくりと
トレイトとは
トレイトはある型が提供しなければならない機能をRustのコンパイラに伝える言語機能です。
メソッド構文で関数を呼び出すのに用いていた、 impl キーワードを思い出して下さい。
継承(Derive)とは
コンパイラには、[#derive]アトリビュートを用いることで型に対して特定のトレイトの標準的な実装を提供する機能があります。より複雑なことを行わせたい場合には、同名のトレイトを手動で実装することも可能です。
なにがなんだか...
まずトレイトからみてみる
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
このプログラムをトレイトを用いて作り直すと,
struct Circle {
x: f64,
y: f64,
radius: f64,
}
trait HasArea {
fn area(&self) -> f64;
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
こうなるのかな?
HasArea
トレイトをCircle
構造体が実装したらなにかいいことがあるのでしょうか。
もう一度トレイトのドキュメントを見てみます。
fn print_area<T>(shape: T) {
println!("This shape has an area of {}", shape.area());
}
このプログラムはエラーを吐くみたいです。
なるほどT
はどんな型にもなれるから,.area()
が使える保証がない(安全性がない)ためだとドキュメントが言っています。
fn print_area<T: HasArea>(shape: T) {
println!("This shape has an area of {}", shape.area());
}
こういうふうにしてHasArea
トレイトを実装しているあらゆる型T
という書き方にしてやれば実行できるようです。
なるほど使いみちがわかってきました。
Derive
ではこのトレイトを構造体に追加できるみたいな感じなんですかね?
Deriveについて
Derive
を使うとどうやら特定のトレイトの標準的な,みんなが使うような実装をカンタンに行うことができるようです。
なるほど,標準的な実装があるのならさっきのトレイトのドキュメントみたいに改めて実装しなくてもいいみたいですね。
このDerive
が使える特定のトレイトは,
Eq
PartialEq
Ord
PartialOrd
Clone
Hash
Default
-
Debug
というふうに決められてるみたいですね〜!
※ドキュメントに載っているZero
はDeprecatedになっているみたいです...
https://www.reddit.com/r/rust/comments/2o3s5v/why_were_stdnum_zero_and_one_traits_deprecated/
おわり
ざっくりとトレイト
とderive
の雰囲気を掴むことができたので,実際に手を動かして行こうと思います。