0Pricing
Learn Rust Coding · บทเรียน

การเปลี่ยนแปลงค่าภายใน: RefCell, Cell

เรียนรู้เกี่ยวกับ `RefCell` และ `Cell` สำหรับการเปลี่ยนแปลงค่าภายใน ทำให้เข้าถึงข้อมูลแบบเปลี่ยนแปลงค่าได้ผ่านการอ้างอิงแบบไม่เปลี่ยนแปลงค่าอย่างปลอดภัย

การเปลี่ยนแปลงค่าภายใน: RefCell, Cell เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน

ความสามารถในการเปลี่ยนแปลงข้อมูลภายในคืออะไร

ใน Rust กฎการยืมมักป้องกันไม่ให้คุณมีการอ้างอิงแบบเปลี่ยนแปลงได้ไปยังข้อมูล หากคุณมีการอ้างอิงแบบอ่านอย่างเดียวไปยังข้อมูลนั้นอยู่แล้ว ซึ่งช่วยรับรองความปลอดภัยของข้อมูล

ความสามารถในการเปลี่ยนแปลงข้อมูลภายใน เป็นรูปแบบการออกแบบที่อนุญาตให้คุณเปลี่ยนแปลงข้อมูลได้ แม้จะมีเพียงการอ้างอิงแบบอ่านอย่างเดียวไปยังข้อมูลนั้น เปรียบเสมือนข้อยกเว้นที่มีการควบคุมจากกฎปกติของ Rust ซึ่งใช้ในสถานการณ์เฉพาะ

`Cell<T>`: สำหรับชนิดข้อมูลที่คัดลอกได้

ชนิดข้อมูล Cell<T> มอบความสามารถในการเปลี่ยนแปลงข้อมูลภายในสำหรับชนิดข้อมูลที่นำเทรต Copy ไปใช้ได้ เช่น จำนวนเต็ม ค่าบูลีน และอักขระ โดยทำงานด้วยการแทนที่ค่าภายใน

  • get(): ส่งคืนสำเนาของค่าภายใน Cell
  • set(value): แทนที่ค่าภายใน Cell ด้วยค่าใหม่

วิธีนี้เรียบง่ายและมีประสิทธิภาพสำหรับข้อมูลขนาดเล็กที่คัดลอกได้

การใช้ `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 ได้มีความสามารถในการเปลี่ยนแปลงค่าภายใน (เช่น String, Vec หรือโครงสร้างข้อมูลแบบกำหนดเอง) คุณจะใช้ RefCell<T>

RefCell ช่วยให้คุณรับ การอ้างอิงแบบเปลี่ยนแปลงได้ไปยังข้อมูลภายใน แต่จะบังคับใช้กฎการยืมของ Rust ขณะ ทำงาน ไม่ใช่ขณะคอมไพล์

การยืมขณะทำงานของ `RefCell`

RefCell มีเมธอดที่คืนค่าตัวชี้อัจฉริยะ:

  • borrow(): คืนค่าเป็น Ref (ตัวชี้อัจฉริยะที่เปลี่ยนแปลงไม่ได้) คุณสามารถมีการยืมแบบเปลี่ยนแปลงไม่ได้หลายรายการพร้อมกันได้
  • borrow_mut(): คืนค่าเป็น RefMut (ตัวชี้อัจฉริยะที่เปลี่ยนแปลงได้) คุณสามารถมีการยืมแบบเปลี่ยนแปลงได้เพียง หนึ่งรายการในแต่ละครั้ง

หากคุณละเมิดกฎเหล่านี้ขณะทำงาน โปรแกรมของคุณจะเกิด panic!

การใช้ `RefCell` (การยืมแบบเปลี่ยนแปลงไม่ได้)

ในที่นี้ เราใช้ borrow() เพื่อรับการอ้างอิงแบบเปลี่ยนแปลงไม่ได้ไปยัง String ภายใน RefCell จากนั้นเราสามารถพิมพ์เนื้อหาของมันได้

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! ขณะทำงาน ซึ่งช่วยป้องกันข้อมูลเสียหาย

ลองเรียกใช้โค้ดนี้เพื่อดูการทำงานจริง! โค้ดจะล้มเหลวพร้อมข้อผิดพลาดว่า "มีการยืมใช้งานอยู่แล้ว"

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

คุณมี struct ที่ต้องเก็บตัวนับแบบเปลี่ยนแปลงได้ (u32) และรายการชื่อแบบเปลี่ยนแปลงได้ (Vec<String>) โดยทั้งสองอย่างต้องได้รับการอัปเดตผ่านการอ้างอิงแบบเปลี่ยนแปลงไม่ได้ไปยัง struct คุณจะใช้ชนิดข้อมูลที่รองรับการเปลี่ยนแปลงค่าภายในชนิดใดกับแต่ละฟิลด์

ทบทวน: การเปลี่ยนแปลงค่าภายใน

คุณได้เรียนรู้รูปแบบการเปลี่ยนแปลงค่าภายในของ Rust ซึ่งช่วยให้แก้ไขข้อมูลผ่านการอ้างอิงแบบเปลี่ยนแปลงไม่ได้ได้อย่างมีการควบคุมและปลอดภัย

  • Cell<T>: สำหรับชนิดข้อมูล Copy โดยจะแทนที่ค่าภายใน
  • RefCell<T>: สำหรับชนิดข้อมูลที่ไม่ใช่ Copy โดยมีการอ้างอิงแบบเปลี่ยนแปลงได้หรือไม่ได้ที่ตรวจสอบขณะทำงาน
  • การละเมิดกฎของ RefCell จะทำให้เกิดแพนิกขณะทำงาน เพื่อรับรองความปลอดภัย

ชนิดข้อมูลเหล่านี้มีความสำคัญต่อรูปแบบต่าง ๆ เช่น ออบเจ็กต์จำลอง การอ้างอิงแบบวนรอบ หรือกรณีที่การอ้างอิงแบบเปลี่ยนแปลงไม่ได้ที่ใช้ร่วมกันจำเป็นต้องติดตามสถานะภายใน

คำถามที่พบบ่อย

บทเรียน “การเปลี่ยนแปลงค่าภายใน: RefCell, Cell” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การเปลี่ยนแปลงค่าภายใน: RefCell, Cell” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การเปลี่ยนแปลงค่าภายใน: RefCell, Cell”

เรียนรู้เกี่ยวกับ `RefCell` และ `Cell` สำหรับการเปลี่ยนแปลงค่าภายใน ทำให้เข้าถึงข้อมูลแบบเปลี่ยนแปลงค่าได้ผ่านการอ้างอิงแบบไม่เปลี่ยนแปลงค่าอย่างปลอดภัย คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 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