Dev Study
← 解説「RefCell<T> — 実行時に借用を検査する」に戻る

サンプルコードで身につける: RefCell<T> — 実行時に借用を検査する

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

1最小の RefCell — let mut なしで書き換える

mut を付けていない変数の中身を、borrow_mut() 経由で書き換える最小の例です。外から見れば counter は不変ですが、RefCell が内側での変更を許してくれます。これが「内部可変性」で、読むときは borrow()、書くときは borrow_mut() と使い分けます。

Rust

2借用ルールは実行時に検査される

「読み取りの借用は同時に複数OK、書き換えの借用は同時に1つだけ」というおなじみのルールが、RefCell では実行時に検査されることを確かめる例です。borrow_mut の結果をブロックで囲んで早めに手放せば、その後は自由に借り直せます。ルール違反はコンパイルエラーではなく panic になる、という違いが最大の注意点です。

Rust

3&self のメソッドで内部カウンタを更新

読み取り専用に見える &self のメソッドの中で、RefCell に包んだカウンタを更新する例です。「外向きの API は不変のまま、内部の統計情報だけ育てたい」という場面の定番構成で、アクセス回数の記録やメトリクス収集がこの形になります。呼び出し側は page を mut にする必要がありません。

Rust

4Rc + RefCell — 共有データをどこからでも書き換える

読み取り共有しかできない Rc と、書き換えを許す RefCell を組み合わせた定番コンビの例です。タスクリストを複数のチームで共有し、どの所有者からも borrow_mut で追加できます。シングルスレッドで「共有かつ可変」が必要になったら、まずこの Rc<RefCell<T>> を思い出してください。

Rust

5計算結果のキャッシュ — &self のまま育てる HashMap

計算結果を RefCell<HashMap> にためておき、2回目以降はキャッシュから返す実務寄りの例です。呼び出し側から見れば square は読み取り専用のメソッドなのに、内部ではキャッシュが育っていきます。出力で「計算した」が1回しか出ないことが、キャッシュが効いた証拠です。

Rust