トレイトオブジェクト

Trait objects

動的サイズ決定型 (DSTs)

トレイトオブジェクトは、以下のポインタを持つワイドポインタ(動的サイズ決定型)

  • 値へのポインタ
  • 仮想メソッドテーブル

トレイトオブジェクトの形

  • Box<dyn SomeTrait>
  • &dyn SomeTrait

トレイトオブジェクトの目的

動的ディスパッチを実現する。

trait Printable {
    fn stringify(&self) -> String;
}

impl Printable for i32 {
    fn stringify(&self) -> String {
        self.to_string()
    }
}

// Box
fn print(a: Box<dyn Printable>) {
    println!("{}", a.stringify());
}

// 参照
fn print2(a: &dyn Printable) {
    println!("{}", a.stringify());
}

fn main() {
    print(Box::new(10));
    print2(&20);
}

関連

トレイトオブジェクトになれないトレイト - あるマのメモ書き

関連型を持つトレイトオブジェクトを宣言する - あるマのメモ書き

参照

https://doc.rust-lang.org/reference/types/trait-object.html

https://qiita.com/hadashiA/items/d0c34a4ba74564337d2f#comment-99db3667a99310a68644

&Foo はトレイトオブジェクトですよ。 トレイトオブジェクトで重要なのは、仮想関数テーブルとオブジェクト実体へのポインタの組であるという点です。トレイトオブジェクトそのものはトレイト境界が実装された型の参照からキャストすればいくらでも得ることができるので、ボクシングを行う必要はありません。

ボクシングされたトレイトオブジェクトの利点は、具体的な型情報が消去された状態でトレイトオブジェクトの所有権を管理できるという点です。なので、逆に言えば所有権を管理する必要がなければボクシングは必要ありません。上に例示したコードのように借用で済むはずです。