Mutabilidade Interior
Em algumas situaçÔes, Ă© necessĂĄrio modificar dados atrĂĄs de uma referĂȘncia compartilhada (somente leitura). Por exemplo, uma estrutura de dados compartilhada pode ter um cache interno e desejar atualizar esse cache a partir de mĂ©todos somente leitura.
O padrĂŁo de "mutabilidade interna" permite acesso exclusivo (mutĂĄvel) por trĂĄs de uma referĂȘncia compartilhada. A biblioteca padrĂŁo fornece vĂĄrias maneiras de fazer isso, garantindo segurança, geralmente realizando uma verificação em tempo de execução.
RefCell
use std::cell::RefCell; fn main() { // Observe que `cell` NĂO Ă© declarado como mutĂĄvel. let cell = RefCell::new(5); { let mut cell_ref = cell.borrow_mut(); *cell_ref = 123; // Isso gera um erro em tempo de execução. // let other = cell.borrow(); // println!("{}", *other); } println!("{cell:?}"); }
Cell
Cell
envolve um valor e permite obter ou definir o valor, mesmo com uma referĂȘncia compartilhada para o Cell
. No entanto, nĂŁo permite nenhuma referĂȘncia ao valor. Como nĂŁo hĂĄ referĂȘncias, as regras de emprĂ©stimo nĂŁo podem ser quebradas.
use std::cell::Cell; fn main() { // Observe que `cell` NĂO Ă© declarado como mutĂĄvel. let cell = Cell::new(5); cell.set(123); println!("{}", cell.get()); }
O principal a ser observado neste slide Ă© que o Rust fornece maneiras seguras de modificar dados por trĂĄs de uma referĂȘncia compartilhada. HĂĄ uma variedade de maneiras de garantir essa segurança, e RefCell
e Cell
sĂŁo duas delas.
-
RefCell
faz cumprir as regras de emprĂ©stimo usuais do Rust (ou vĂĄrias referĂȘncias compartilhadas ou uma Ășnica referĂȘncia exclusiva) com uma verificação em tempo de execução. Neste caso, todos os emprĂ©stimos sĂŁo muito curtos e nunca se sobrepĂ”em, entĂŁo as verificaçÔes sempre tĂȘm sucesso.- O bloco extra no exemplo de
RefCell
é para encerrar o empréstimo criado pela chamada aborrow_mut
antes de imprimir ocell
. Tentar imprimir umRefCell
emprestado mostra apenas a mensagem"{borrowed}"
.
- O bloco extra no exemplo de
-
Cell
é um meio mais simples de garantir a segurança: ele tem um métodoset
que recebe&self
. Isso não precisa de uma verificação em tempo de execução, mas requer mover valores, o que pode ter seu próprio custo. -
Tanto
RefCell
quantoCell
sĂŁo!Sync
, o que significa que&RefCell
e&Cell
nĂŁo podem ser passados entre threads. Isso impede que duas threads tentem acessar ocell
ao mesmo tempo.