Dev Study
← 解説「Deref — スマートポインタを参照のように使う」に戻る

サンプルコードで身につける: Deref — スマートポインタを参照のように使う

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1最小の Deref 実装 — * の意味を自分で決める

自作の MyBox に Deref を実装し、* で中身の値に届くようにする最小の例です。*m と書いた瞬間、コンパイラがそれを deref() の呼び出しに置き換えています。type Target は「* で取り出される型の宣言」という決まり文句で、この2点が Deref 実装の全部です。

Rust

2参照外し型強制 — &Box<String> がそのまま &str になる

&str を取る関数に &String も &Box<String> もそのまま渡せることを確かめる例です。Deref の実装をたどって &Box<String> → &String → &str と何段でも自動変換されるのが「参照外し型強制」です。普段なにげなく String を &str の引数に渡せていた理由が、まさにこの仕組みです。

Rust

3メソッド呼び出しも deref を通る

Deref を実装した型では、* を書かなくても中身のメソッドをドット記法で直接呼べることを示す例です。w.len() と書くと、コンパイラが「Wrapper には len がない → deref して String で探す」という探索を自動でやってくれます。Box の中身のメソッドがそのまま呼べていたのも同じ仕組みです。

Rust

4newtype パターン — 専用の型に str の能力を持たせる

メールアドレス専用の型 Email を作りつつ、Deref で Target = str にして文字列の読み取りメソッドをそのまま使えるようにする実務寄りの例です。「ただの String と区別できる型にしたいが、読み取り操作は委譲したい」という newtype パターンの定番構成です。ライブラリのラッパー型が中身のメソッドを使えるのも、多くはこの作りです。

Rust

5deref の呼び出しを観測する — * は隠れたメソッド呼び出し

deref() の中に println! を仕込み、* を書くたびに本当に deref が呼ばれていることを出力で観測する例です。「* は演算子ではなく deref() というメソッドの呼び出し」という抽象的な説明が、目に見える形で確認できます。デバッグ用に値へのアクセスを観測したいときにも応用できる作りです。

Rust