Внутрішня мутабельність
У деяких ситуаціях необхідно модифікувати дані за спільним (доступним лише для читання) посиланням. Наприклад, структура даних зі спільним доступом може мати внутрішній кеш, і ви хочете оновити цей кеш методами, доступними лише для читання.
Паттерн “внутрішня мутабельність” дозволяє ексклюзивний (мутабельний) доступ за спільним посиланням. Стандартна бібліотека надає декілька способів зробити це, забезпечуючи при цьому безпеку, як правило, шляхом виконання перевірки під час виконання.
Cell
Cell обгортає значення і дозволяє отримати або встановити значення, використовуючи лише спільне посилання на Cell. Однак, вона не дозволяє жодних посилань на внутрішнє значення. Оскільки посилань немає, правила запозичення не можуть бути порушені.
use std::cell::Cell; fn main() { // Зауважте, що `cell` НЕ оголошено як мутабельну. let cell = Cell::new(5); cell.set(123); println!("{}", cell.get()); }
RefCell
RefCell дозволяє отримувати доступ до обгорнутого значення та змінювати його, надаючи альтернативні типи Ref та RefMut, які імітують &T/&mut T, не будучи насправді Rust посиланнями.
Ці типи виконують динамічні перевірки за допомогою лічильника в RefCell, щоб запобігти існуванню RefMut поряд з іншим Ref/RefMut.
Завдяки реалізації Deref (і DerefMut для RefMut), ці типи дозволяють викликати методи за внутрішнім значенням, не дозволяючи посиланням втекти.
use std::cell::RefCell; fn main() { // Зауважте, що `cell` НЕ оголошено як мутабельну. let cell = RefCell::new(5); { let mut cell_ref = cell.borrow_mut(); *cell_ref = 123; // Це спричиняє помилку під час виконання. // let other = cell.borrow(); // println!("{}", *other); } println!("{cell:?}"); }
Основне, що можна винести з цього слайду, це те, що Rust надає безпечні способи модифікації даних за спільним посиланням. Існує безліч способів забезпечити цю захищеність, і RefCell та Cell - два з них.
- 
RefCellзастосовує звичайні правила запозичень Rust (або декілька спільних посилань, або одне ексклюзивне посилання) з перевіркою під час виконання. У цьому випадку всі запозичення дуже короткі і ніколи не перетинаються, тому перевірки завжди проходять успішно.- Додатковий блок у прикладі 
RefCellпризначений для завершення запозичення, створеного викликомborrow_mut, до того, як ми надрукуємо комірку. Спроба надрукувати запозичену коміркуRefCellпросто покаже повідомлення"{borrowed}". 
 - Додатковий блок у прикладі 
 - 
Cellє найпростішим засобом гарантування безпеки: він має методset, який приймає значення&self. Це не потребує перевірки під час виконання, але вимагає переміщення значень, що може мати свою ціну. - 
І
RefCell, іCellє!Sync, що означає, що&RefCellі&Cellне можна передавати між потоками. Це запобігає спробам двох потоків одночасно отримати доступ до комірки.