wiki/content/20200929141711-deref_trait.md

110 lines
2.1 KiB
Markdown
Raw Permalink Normal View History

2024-05-06 20:40:05 +00:00
---
2024-10-30 17:34:11 +00:00
date: 2020-09-29
2024-05-06 20:40:05 +00:00
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);
}
```