Трейт DerefMut
Трейт DerefMut определяет поведение
оператора изменяемого разыменования *
для умных указателей. Если тип реализует
DerefMut, то по изменяемой ссылке на
этот тип можно получить изменяемую ссылку на
внутренние данные и, например, вызывать методы,
которые требуют &mut self.
Трейт является продолжением трейта Deref:
Deref даёт доступ к данным только для чтения,
а DerefMut - ещё и для изменения. Метод
deref_mut принимает изменяемую ссылку
&mut self и возвращает изменяемую ссылку
&mut Self::Target на целевой тип.
Синтаксис
trait DerefMut: Deref
{
fn deref_mut(&mut self) -> &mut Self::Target;
}
Пример
Реализуем простой умный указатель MyBox,
который хранит значение и позволяет изменять его
через DerefMut. Для этого также потребуется
реализовать трейт Deref:
use std::ops::{Deref, DerefMut};
struct MyBox<T>(T);
impl<T> MyBox<T>
{
fn new(x: T) -> MyBox<T>
{
MyBox(x)
}
}
impl<T> Deref for MyBox<T>
{
type Target = T;
fn deref(&self) -> &T
{
&self.0
}
}
impl<T> DerefMut for MyBox<T>
{
fn deref_mut(&mut self) -> &mut T
{
&mut self.0
}
}
fn main()
{
let mut b = MyBox::new(5);
*b = 10;
println!("{}", *b);
}
Результат выполнения кода:
10
Пример
Благодаря DerefMut можно вызывать методы,
требующие изменяемую ссылку, прямо через умный
указатель. Давайте изменим строку внутри
MyBox<String>:
use std::ops::{Deref, DerefMut};
struct MyBox<T>(T);
impl<T> MyBox<T>
{
fn new(x: T) -> MyBox<T>
{
MyBox(x)
}
}
impl<T> Deref for MyBox<T>
{
type Target = T;
fn deref(&self) -> &T
{
&self.0
}
}
impl<T> DerefMut for MyBox<T>
{
fn deref_mut(&mut self) -> &mut T
{
&mut self.0
}
}
fn main()
{
let mut b = MyBox::new(String::from("abcde"));
b.push_str("12345");
println!("{}", *b);
}
Результат выполнения кода:
"abcde12345"
Пример
Трейт DerefMut часто реализуется для
обёрток над векторами. Давайте создадим
MyVec и добавим в него элемент через
метод push:
use std::ops::{Deref, DerefMut};
struct MyVec<T>(Vec<T>);
impl<T> MyVec<T>
{
fn new() -> MyVec<T>
{
MyVec(Vec::new())
}
}
impl<T> Deref for MyVec<T>
{
type Target = Vec<T>;
fn deref(&self) -> &Vec<T>
{
&self.0
}
}
impl<T> DerefMut for MyVec<T>
{
fn deref_mut(&mut self) -> &mut Vec<T>
{
&mut self.0
}
}
fn main()
{
let mut v = MyVec::new();
v.push(1);
v.push(2);
v.push(3);
println!("{:?}", *v);
}
Результат выполнения кода:
[1, 2, 3]
Смотрите также
-
трейт
Deref,
который позволяет разыменовывать умный указатель только для чтения -
трейт
trait,
который описывает общее поведение типов в Rust -
трейт
impl for,
который позволяет реализовать трейт для конкретного типа -
трейт
trait bound,
который задаёт ограничения на обобщённые типы