内部可変性:RefCell、Cell
不変参照を通じて安全にデータへ可変アクセスできる、`RefCell`と`Cell`による内部可変性について学びます。
「内部可変性:RefCell、Cell」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン2/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全3レッスンが含まれています。
内部可変性とは
Rustでは通常、データへの不変参照をすでに持っている場合、そのデータへの可変参照を持つことは借用規則によって禁止されます。これによりデータの安全性が保たれます。
内部可変性は、不変参照しか持っていない場合でもデータを変更できるようにするデザインパターンです。特定の状況で使う、Rustの通常の規則に対する制御された例外のようなものです。
`Cell<T>`:Copy型向け
Cell<T>型は、Copy traitを実装する型(整数、ブール値、文字など)に内部可変性を提供します。内部の値を置き換えることで機能します。
get():Cell内部の値のコピーを返します。set(value):Cell内部の値を新しい値に置き換えます。
小さく、コピー可能なデータに適した、シンプルで効率的な機能です。
`Cell`で値を更新する
これはCellの基本的な例です。Cell自体が不変として宣言されているにもかかわらず、内部の値を変更できることに注目してください。
use std::cell::Cell;
fn main() {
let my_num = Cell::new(10);
println!("Initial value: {}", my_num.get());
my_num.set(20);
println!("Updated value: {}", my_num.get());
let x = &my_num;
x.set(30); // Still works via immutable reference!
println!("Via immutable ref: {}", my_num.get());
}`RefCell<T>`:Copy以外の型向け
Copyを実装していない型(String、Vec、カスタム構造体など)に内部可変性が必要な場合は、RefCell<T>を使用します。
RefCellを使うと内部データへの可変参照を取得できますが、Rustの借用規則はコンパイル時ではなく実行時に適用されます。
`RefCell`の実行時借用
RefCellには、スマートポインターを返すメソッドが用意されています。
borrow():Ref(不変スマートポインター)を返します。不変借用は同時に複数保持できます。borrow_mut():RefMut(可変スマートポインター)を返します。可変借用は同時に1つだけ保持できます。
実行時にこれらの規則に違反すると、プログラムはpanic!します。
`RefCell`の使用(不変借用)
ここでは、borrow()を使ってRefCell内のStringへの不変参照を取得します。その内容を出力できます。
use std::cell::RefCell;
fn main() {
let my_string_cell = RefCell::new(String::from("Hello"));
let s1 = my_string_cell.borrow();
println!("Value: {}", *s1); // Dereference Ref to get String
let s2 = my_string_cell.borrow(); // Multiple immutable borrows are fine
println!("Another value: {}", *s2);
}`RefCell`の使用(可変借用)
次に、borrow_mut()を使って可変参照を取得します。これによりStringを変更できます。s_mutがスコープ内にある間は、他の借用(可変・不変を問わず)は許可されないことに注意してください。
use std::cell::RefCell;
fn main() {
let my_string_cell = RefCell::new(String::from("World"));
{ // Scope for the mutable borrow
let mut s_mut = my_string_cell.borrow_mut();
s_mut.push_str(", Rust!");
}
// s_mut is out of scope here, so we can borrow again
let s_final = my_string_cell.borrow();
println!("Final value: {}", *s_final);
}`RefCell`の実行時パニック
別の可変借用(またはいずれかの不変借用)が有効な状態で可変借用を取得しようとすると、RefCellは実行時にプログラムをpanic!させます。これによりデータの破損を防ぎます。
このコードを実行して、動作を確認してみましょう。「borrow already in use」というエラーでクラッシュします。
use std::cell::RefCell;
fn main() {
let my_value = RefCell::new(vec![1, 2, 3]);
let _first_mut_borrow = my_value.borrow_mut();
println!("First mutable borrow is active.");
// This line will cause a runtime panic!
// Try commenting it out to see the program run successfully.
let _second_mut_borrow = my_value.borrow_mut();
println!("This line will not be reached.");
}`Cell`と`RefCell`のまとめ
CellとRefCellのどちらを選ぶかは、データ型と、そのデータをどのように扱う必要があるかによって決まります。
Cell<T>:Copyを実装する型に使用します。値全体を置き換えるため、一般的によりシンプルで高性能です。RefCell<T>:Copyを実装しない型に使用します。内部データへの参照を提供し、実行時に借用規則を適用することで、より複雑な変更を可能にします。
クイックチェック:CellとRefCellのどちらを使いますか?
可変カウンター(u32)と可変な名前のリスト(Vec<String>)を格納する必要があるstructがあり、どちらもstructへの不変参照を通じて更新する必要があるとします。それぞれのフィールドには、どの内部可変性の型を使用しますか?
振り返り:内部可変性
Rustの内部可変性パターンについて学びました。これは、制御された安全な方法で、不変参照を通じてデータを変更できるようにするものです。
Cell<T>:Copy型に使用し、内部の値を置き換えます。RefCell<T>:非Copy型に使用し、実行時に検査される可変・不変参照を提供します。RefCellの規則に違反すると実行時パニックが発生し、安全性が保たれます。
これらの型は、モックオブジェクト、循環参照、共有された不変参照から内部状態を追跡する場合などのパターンで重要です。
よくある質問
「内部可変性:RefCell、Cell」レッスンは無料ですか?
はい。「内部可変性:RefCell、Cell」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全3レッスンが含まれています。
「内部可変性:RefCell、Cell」で何を学びますか?
不変参照を通じて安全にデータへ可変アクセスできる、`RefCell`と`Cell`による内部可変性について学びます。 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn Rust Codingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/3です。
「内部可変性:RefCell、Cell」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn Rust Codingレッスンでコードを書いて実行できますか?
はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Box、Rc、Arcスマートポインタ
- 内部可変性:RefCell、Cell
- スレッドによる恐れのない並行処理