self
ma typ &mut Foo
w print
, to znaczy, że jest wypożyczony zmienny odniesienie do wartości typu Foo
. Typy w Rust przenoszą własność domyślnie, to znaczy, biorąc coś za wartość, statycznie unieważnią źródło i powstrzymają programistę przed ponownym użyciem (chyba że zostanie ponownie zainicjowany). W tym przypadku, unwrap
ma podpis:
impl Option<T> {
fn unwrap(self) -> T { ...
to znaczy, że bierze wartość Option
przez wartość, a więc starają się spożywać go na własność. W związku z tym self.maybe_file.unwrap()
próbuje pobrać dane w postaci maybe_file
, co pozostawiłoby self
wskazujące na częściowo nieprawidłowe dane (niedozwolone jest używanie pola maybe_file
). Kompilator nie może tego egzekwować za pomocą pożyczonych odniesień, które muszą być zawsze aktualne, ponieważ mogą wskazywać gdziekolwiek, więc wyprowadzanie się jest nielegalne.
Na szczęście, można uniknąć tego problemu: metoda as_ref
tworzy Option<&T>
się o &Option<T>
i metoda as_mut
tworzy Option<&mut T>
się o &mut Option<T>
. Powstały Option
nie jest już wtedy za punkt odniesienia, a więc jest to legalne spożywanie go przez unwrap
:
let mut file = self.maybe_file.as_mut().unwrap();
ta różni się nieznacznie, ponieważ file
ma typ &mut File
zamiast File
, ale na szczęście &mut File
jest wszystko, co jest niezbędne dla reszta kodu.
Innym podejściem do podejmowania tej pracy jest za pomocą ręcznego dopasowywania wzoru:
match self.maybe_file {
Some(ref mut file) => println!(...),
None => panic!("error: file was missing")
}
To robi dokładnie to samo co .as_mut().unwrap()
tylko bardziej wyraźny: the ref mut
jest utworzyć odwołanie skierowaną bezpośrednio do pamięci zajmowanej przez self.maybe_file
, podobnie jak as_mut
.
Dzięki, ta odpowiedź bardzo mi pomogła! – Reignbeaux