wiki/content/20200929141711-deref_trait.md

109 lines
2.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
date: 20200929
id: d2d028c8-733f-4cdb-b096-89cf8b3de961
title: Deref Trait
---
# Introduction
Implementing the `Deref` trait allows you to customize the behavior of
the *dereference operator*, \* (as opposed to the multiplication or glob
operator). By implementing `Deref` in such a way that a smart pointer
can be treated like a regular reference, you can write code that
operates on references and use that code with smart pointers too:
``` rust
fn main() {
let x = 5;
let y = &x;
assert_eq!(5, x);
assert_eq!(5, *y);
}
```
# Box
A [Box\<T\>](20200929135609-box_t) can also be used:
``` rust
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
```
# Deref Trait
``` rust
use std::ops::Deref;
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
fn main() {
let x = 5;
let y = MyBox::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
```
# Deref Coercion
*Deref coercion* is a convenience that Rust performs on arguments to
functions and methods. Deref coercion works only on types that implement
the Deref trait. Deref coercion converts such a type into a reference to
another type. For example, deref coercion can convert `&String` to
`&str` because `String` implements the `Deref` trait such that it
returns `str`. Deref coercion happens automatically when we pass a
reference to a particular types value as an argument to a function or
method that doesnt match the parameter type in the function or method
definition. A sequence of calls to the `deref` method converts the type
we provided into the type the parameter needs.
``` rust
use std::ops::Deref;
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
fn hello(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
let m = MyBox::new(String::from("Rust"));
hello(&m);
}
```