実践Rust入門 9日目

8章1〜2節。

トレイトの基本について。
サンプルコードを打ち込みながら読むスタイル。

今までの章に比べると、ソース多め文章少なめで読みやすかった。

ただ、サンプルコードに見慣れない英単語が多く使われてて混乱した。
まぁ僕の英語力の無さの問題が大きいのかもしれないけれども。
もっと簡単な単語にしてくれると嬉しいんだけどなぁ。。。

「Coord」や「Cartesian」とか、グラフィック系やってる人はよく見かける単語なのだろうか。
はたまた一般教養なのだろうか。。。

よく見かけるサンプルの「apple」や「banana」の偉大さを感じた。

おぼえがき
  • トレイト
    • Javaでいうインタフェース的な
    • 構造体だけでなく、タプルや列挙型などに対しても定義できる
    • 定義: trait TraitName { fn func(arg: i32) -> i32; }
    • 実装: impl TraitName for TypeName { fn func(arg: i32) -> i32 { 0 } }
  • トレイト境界
    • ジェネリクスや引数にトレイトを指定して、受け入れる型を制限する
    • 受け入れる対象が必要な関数を持っていることを保証する
    • 指定方法は3種類
      • ジェネリクスの型パラメータで指定
        • fn func<T: TraitName>(arg: T){}
        • fn func<T: TraitName1 + TraitName2>(arg: T){}
      • where節で指定
        • fn func<T>(arg:T) where T: TraitName, {}
        • 引数を使った型に対しても指定できる。すっごい
          • where (T, T): TraitName ... 引数の型を使ったタプルに対する指定の例
      • 関数の引数で指定(impl Trait構文)
        • fn func(arg: impl TraitName){}
        • 上2つと違って、シグネチャに複数回出てくる型に対しては使えない
  • トレイトは継承もできる
    • クラスベースの継承とは別物らしい
    • trait TraitName: BaseTraitName { fn ex_method(); }
    • 継承後のトレイトを実装する型は、継承元の全てのトレイトを実装している必要がある
  • トレイト定義に関数のデフォルト実装も定義できる
    • デフォルト実装した関数は、トレイトを実装する型で定義を省略できる
    • トレイトを実装する型で、同名の関数を実装すれば、デフォルト実装は上書きできる
  • トレイトを他のモジュールに公開するには
    • トレイトとトレイトを実装する型を公開しておく
      • pub trait TraitName {}
      • pub struct ImplTraitStruct {}
    • トレイト内の関数はデフォルトで公開なのでpubは要らない
  • トレイトコヒーレンシー
    • 他クレートで定義されたトレイトを、他クレートで定義された型に対しては実装できない
    • 実装の
  • 自動導出
    • #[derive(TraitName)アトリビュートで、トレイトを自動で実装してくれる
    • 標準ライブラリで導出可能なのは以下。これらは付けた方が良いらしい
      • Clone
      • Copy
      • Debug
      • Default
      • Eq
      • Hash
      • Ord
      • PartialEq
      • PartialOrd
      • 参考
    • 自動導出できないものを指定すると、コンパイルエラーになる
    • 自作のライブラリのトレイトをderiveに対応させるには、「手続きマクロ」という機能を使うっぽい
      • 本書では説明なし
  • トレイトにジェネリクスを指定できる
    • trait TraitName<T> {}
    • impl TraitName<T> for TypeName { fn func(self)-> T; }
    • 例 u8型に対してu64型にキャストするトレイトを実装
      • impl As<T> { fn cast(self) ->T;
      • impl As<u64> for u8 { fn cast(self) -> u64 { self as u64 } }
        • 実装は型を指定することもできる
  • トレイトとオーバーロード
    • instance.func()は、TraitType::func(&instance)の糖衣構文
    • メソッドディスパッチは、実行時に分かる値でメソッドを使い分ける(動的ディスパッチ)
    • オーバーロードは、コード上の型でメソッドを使い分ける(静的ディスパッチ)
課題

実践Rust入門[言語仕様から開発手法まで]

実践Rust入門[言語仕様から開発手法まで]