mizdra's poem

雑なこと (日記/技術ポエム/メモ/…) を書くブログです. 真に受けないでください.

Rustのトレイト勉強メモ

概要

Rustのトレイトについて勉強したのでメモ.

読んだもの

トレイト

  • ポリモーフィズムの一種で, 部分型多相を実現するもの
  • 複数の型に共通する振舞いを抽象化できる
  • よくある間違い
    • 🙅 共通のデータ構造に対する抽象化をすることが目的ではない
      • 🙆 共通の振舞いに対する抽象化をすることが目的
      • トレイトでは振舞いを定義できるが, 抽象フィールドに相当するものが定義できない
      • トレイトの命名も「どんなデータ構造を持つのか」ではなく「どんな振舞いを持つのか」を的確に表したもののほうが好ましい?
        • FigureよりもHasAreaのほうが好ましい?
      • structブロックにデータ構造を記述し, implブロックに振舞いの実装を記述するという考え方
    • 🙅 変数の型や配列の要素の型, 型パラメータ, 引数の型, 戻り値の型などにトレイトを指定できない
      • 🙆 主にトレイト境界に指定できる
      • 詳しくは「トレイトオブジェクト」にて説明
  • サンプルコード: https://play.rust-lang.org/?gist=a1c734a7db83efa1976e96af37b4b5a9&version=stable&mode=debug

トレイト境界

トレイトの制限

トレイトオブジェクト

  • 動的ディスパッチを実現する機能
  • fat pointerの一種
  • std::rawモジュールにトレイトオブジェクトを表す構造体が定義されている
    • 参考: raw.rs.html -- source
    • TraitObjectは暗黙にSizedを実装しているので変数の型などに指定できる
    • x86-64環境では16byte
  • Box<T> or &T or &mut Tを使うことでコンパイラによりトレイトオブジェクトとして特別扱いされる
  • Box<T>&Tの違い
    • Box<T>はヒープ上にあるT型のデータへのポインタ (pointer) を持つデータを, &Tは (ヒープ上やスタック上などのあらゆる場所にある) T型のデータへの参照 (reference) を表す
      • 注: &Box<T>は参照だが, Box<T>は参照ではない
    • &Tは参照なので, Rustの所有権システムに関する借用のルールが適用される
  • 仮想関数テーブルを用いた動的ディスパッチが行われる
  • 例外的に本来使用できないところにトレイトを使用できる場合もある
  • 例: Box<T>Tは型パラメータであるがトレイトを指定できる
  • トレイトオブジェクトにできるトレイトの条件は「そのトレイトがオブジェクト安全であること」
    • 詳細は「オブジェクト安全」にて
  • 参考: トレイトオブジェクト
  • サンプルコード: https://play.rust-lang.org/?gist=057fb336f09229c8cad5b86e5c9aa665&version=stable&mode=debug

オブジェクト安全

  • トレイトがオブジェクト安全であることの条件
    1. トレイトがSelf: Sizedを要求しないこと
      • トレイトが取りうるサイズが不定という条件に違反する
      • そもそもトレイトはSizedを実装していないので当然といえば当然
    2. トレイトのメソッド全てがオブジェクト安全であること
  • メソッドがオブジェクト安全であることの条件
    1. どのような型パラメータも持ってはならない
      • 型パラメータを持つとそのメソッドを特殊化しなければならないが, トレイトオブジェクトに対して特殊化することは難しそうだし, 納得できる
    2. Selfを使ってはならない
  • 参考: トレイトオブジェクト

dyn Trait

  • ある型がトレイトオブジェクトであることを明示するために導入された新記法
  • Box<Sized>Box<Trait>でどちらがトレイトオブジェクトでそうでないかひと目で区別できないという問題を解決する
    • 例: Box<Trait>Box<dyn Trait>に置き換える
  • まだ安定化されていない機能
  • 対応表
従来記法 新記法
Box<Trait> Box<dyn Trait>
&Trait &dyn Trait
&mut Trait &mut dyn Trait

impl Trait