0Pricing
Learn Rust Coding · レッスン

内部可変性: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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Box、Rc、Arcスマートポインタ
  2. 内部可変性:RefCell、Cell
  3. スレッドによる恐れのない並行処理
← Learn Rust Codingに戻る