The Deref Trait
Deref teaches a wrapper type how to act like the value it's holding, so you can use it almost as if it wasn't wrapped at all.In this page:
impl Deref for Name {
type Target = Inner;
fn deref(&self) -> &Self::Target {
&self.field
}
}
Box Already Implements Deref
Box<T> implements Deref, which is why *boxed_value gives you the inner value directly, even though Box itself is a distinct type.
Example: Box Already Implements Deref
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `boxed`, set to `Box::new(5)`
let boxed = Box::new(5);
// Print "Dereferenced: {}" to the console, substituting in `*boxed` (with a trailing newline)
println!("Dereferenced: {}", *boxed);
}
Login to try C/C++/Java/PHP code in the editor
Implementing Deref for a Custom Wrapper
You can implement Deref for your own wrapper struct, defining what *wrapper should produce and enabling deref coercion for method calls.
Example: Implementing Deref for a Custom Wrapper
// Bring `std::ops::Deref` into scope
use std::ops::Deref;
// Define a struct `MyBox` to group related fields together
struct MyBox<T>(T);
// Implement the `Deref` trait for `MyBox`
impl<T> Deref for MyBox<T> {
type Target = T;
// Define the function `deref` taking `&self` and returning a `&T`
fn deref(&self) -> &T {
&self.0
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `wrapped`, set to `MyBox(String::from("wrapped value"))`
let wrapped = MyBox(String::from("wrapped value"));
// Print "{}" to the console, substituting in `*wrapped` (with a trailing newline)
println!("{}", *wrapped);
}
Login to try C/C++/Java/PHP code in the editor
Deref Coercion in Method Calls
When calling a method, Rust automatically applies deref coercion, converting &MyBox<String> into &str as needed, so you can call String/str methods directly on the wrapper.
Example: Deref Coercion in Method Calls
// Bring `std::ops::Deref` into scope
use std::ops::Deref;
// Define a struct `MyBox` to group related fields together
struct MyBox<T>(T);
// Implement the `Deref` trait for `MyBox`
impl<T> Deref for MyBox<T> {
type Target = T;
// Define the function `deref` taking `&self` and returning a `&T`
fn deref(&self) -> &T {
&self.0
}
}
// Define the function `print_len` taking `s`
fn print_len(s: &str) {
// Print "Length: {}" to the console, substituting in `s.len()` (with a trailing newline)
println!("Length: {}", s.len());
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `wrapped`, set to `MyBox(String::from("coerced"))`
let wrapped = MyBox(String::from("coerced"));
print_len(&wrapped);
}
Login to try C/C++/Java/PHP code in the editor
DerefMut for Mutable Access
Implementing DerefMut alongside Deref allows mutable dereferencing (*wrapper = ... or calling &mut self methods) through the wrapper type as well.
Example: DerefMut for Mutable Access
// Bring `std::ops::{Deref, DerefMut}` into scope
use std::ops::{Deref, DerefMut};
// Define a struct `MyBox` to group related fields together
struct MyBox<T>(T);
// Implement the `Deref` trait for `MyBox`
impl<T> Deref for MyBox<T> {
type Target = T;
// Define the function `deref` taking `&self` and returning a `&T { &self.0 }`
fn deref(&self) -> &T { &self.0 }
}
// Implement the `DerefMut` trait for `MyBox`
impl<T> DerefMut for MyBox<T> {
// Define the function `deref_mut` taking `self` and returning a `&mut T { &mut self.0 }`
fn deref_mut(&mut self) -> &mut T { &mut self.0 }
}
// Entry point: execution of the program starts here
fn main() {
// Declare a mutable variable `wrapped`, initialized to `MyBox(10)`
let mut wrapped = MyBox(10);
*wrapped += 5;
// Print "{}" to the console, substituting in `*wrapped` (with a trailing newline)
println!("{}", *wrapped);
}
Login to try C/C++/Java/PHP code in the editor
- Forgetting
Derefonly affects how*valueand method calls behave -- it does not change the wrapper's own type identity. - Assuming implementing
Derefalso gives youDerefMutautomatically -- mutable dereferencing requires a separate trait implementation. - Overusing custom
Derefimplementations to fake inheritance-like behavior, which can make code confusing to follow.
- Implementing
Dereflets a custom type be dereferenced with*, similar to howBox<T>works. - Deref coercion automatically converts
&MyTypeinto&InnerTypewhen calling methods, reducing manual dereferencing. DerefMutis the corresponding trait for mutable dereferencing and must be implemented separately.Derefis what allows smart pointers likeBox,Rc, and custom wrapper types to be used almost like their inner value.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: