Трейт Deref
Трейт Deref позволяет указать,
как тип должен вести себя при разыменовании
с помощью оператора *. Методом
deref трейт принимает ссылку
на значение и возвращает ссылку на
внутреннее значение, к которому нужно
выполнить разыменование.
Реализация Deref включает механизм
автоматического разыменования (deref coercion),
благодаря которому ссылка на тип может
автоматически превращаться в ссылку на
другой тип при передаче в функции и методы.
Синтаксис
impl Deref for Type
{
type Target = TargetType;
fn deref(&self) -> &Self::Target
{
// return reference to inner value
}
}
Пример
Давайте создадим структуру MyBox,
которая хранит значение, и реализуем
для неё трейт Deref:
use std::ops::Deref;
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) -> &Self::Target
{
&self.0
}
}
fn main()
{
let b = MyBox::new(5);
let val = *b;
println!("{}", val);
}
Результат выполнения кода:
5
Пример
Давайте рассмотрим автоматическое разыменование при передаче значения в функцию, которая принимает ссылку на строку:
use std::ops::Deref;
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) -> &Self::Target
{
&self.0
}
}
fn hello(name: &str)
{
println!("Hello, {}!", name);
}
fn main()
{
let m = MyBox::new(String::from("abcde"));
hello(&m);
}
Результат выполнения кода:
Hello, abcde!
Пример
Давайте используем Deref для доступа
к методам внутреннего типа через внешний тип:
use std::ops::Deref;
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) -> &Self::Target
{
&self.0
}
}
fn main()
{
let m = MyBox::new(String::from("abcde"));
let len = m.len();
println!("{}", len);
}
Результат выполнения кода:
5