liveBook · Manning

Trait

As explained in Rust in Action: Systems programming concepts and techniques

The trait keyword is Rust's reserved keyword for declaring a trait.

A trait names behavior that multiple types can share. The `trait` keyword declares that behavior; `impl` supplies it for a particular type. Think of a trait as a contract: a type that implements it provides the required methods. section 3.6 section 3.6.1

A file-like value might read bytes from a disk, memory, or a network connection. A `Read` trait can describe the reading operation without choosing where the bytes come from. In the small example below, `File` implements `read` by returning `Ok(0)`; the method does not yet fetch any bytes. section 3.6 section 3.6.1

Listing 3.12 Defining the bare bones of a Read trait for File
 #![allow(unused_variables)]        #1
 
 #[derive(Debug)]
 struct File;                       #2
 
 trait Read {                       #3
     fn read(
       self: &Self,
       save_to: &mut Vec<u8>,
     ) -> Result<usize, String>;    #4
 }
 
 impl Read for File {
     fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
         Ok(0)                      #5
     }
 }
 
 fn main() {
     let f = File{};
     let mut buffer = vec!();
     let n_bytes = f.read(&mut buffer).unwrap();
     println!("{} byte(s) read from {:?}", n_bytes, f);
 }

Compare `trait Read`, which declares a method, with `impl Read for File`, which supplies its body. `main` calls that method on a `File` value. section 3.6.1

Traits also sit behind familiar syntax. `PartialEq` enables `==`, while `std::ops::Add` defines addition. A generic function cannot add values of an unrestricted type `T`: the bound `T: std::ops::Add<Output = T>` requires a type that supports the operation. During compilation, `a + b` becomes a call to `a.add(b)`. section 3.6.1 section 2.8.2

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Works through a trait declaration, an implementation, and an operator trait bound, but does not develop a comprehensive trait reference.
Examples
Uses a Read implementation for File, an Add-bounded function called with several types, and PartialEq-backed equality.
What it assumes
Introduces traits after typed functions and generic functions, using familiar file operations to make the new syntax concrete.
What you can do after
Build it from scratch: declare a trait, implement it for a type, and add a trait bound to a generic function.
How it connects
Links traits to generic functions, operator overloading, structs, and impl blocks.

Also explained in

Compare how 4 books explain trait →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.