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



