Ваш, вероятно, самый эффективный способ, но в теории это необязательно, и один может быть более элегантным.
Другой способ сделать это - использовать объект черты в этом случае - иметь переменную типа dyn DerefMut<Vec<Page>>
. Это в основном означает, что эта переменная может содержать любой тип, который реализует черту DerefMut<Vec<Page>>>
, два типа, которые делают это &mut Vec<Page>
и Vec<Page>
, в этом случае переменная может содержать любой из них, но на содержимое можно ссылаться только через DerefMut
.
Таким образом, следующий код работает в качестве иллюстрации:
struct Foo {
inner : Option<Vec<i32>>,
}
impl Foo {
fn new () -> Self {
Foo { inner : None }
}
fn init (&mut self) {
self.inner = Some(Vec::new())
}
fn get_mut_ref (&mut self) -> Option<&mut Vec<i32>> {
self.inner.as_mut()
}
}
fn main () {
let mut foo : Foo = Foo::new();
let mut m : Box<dyn AsMut<Vec<i32>>> = match foo.get_mut_ref() {
Some(r) => Box::new(r),
None => Box::new(vec![1,2,3]),
};
m.as_mut().as_mut().push(4);
}
Ключом здесь является тип Box<dyn AsMut<Vec<i32>>
; это означает, что это может быть ящик, который содержит любой тип, так что тип реализует AsMut<Vec<i32>>
, потому что он в штучной упаковке, нам также нужно .as_mut().as_mut()
, чтобы получить из него фактический &mut <Vec<i32>>
.
Потому что разные типы могут иметь разные размеры; они также не могут быть размещены в стеке, поэтому они должны быть позади некоторого указателя, поэтому обычно выбирается Box
, и в этом случае необходимо, чтобы перед обычным указателем, sans , принадлежащим его pointee проблемы, аналогичные тем, с которыми вы сталкиваетесь.
Можно утверждать, что этот код более элегантный, но ваш, безусловно, более эффективен и не требует дальнейшего выделения кучи.