A trait defines methods a type can implement. Implementing the trait gives the type that behavior.

Program

Play the program to implement a Greet trait for a struct.

traits.rs
Replay: real traced execution (multi-file project)
trait Greet {
    fn hello(&self) -> String;
}

struct Person {
    name: String,
}

impl Greet for Person {
    fn hello(&self) -> String {
        format!("Hi, {}", self.name)
    }
}

fn main() {
    let p = Person { name: String::from("Ada") };
    let msg = p.hello();
    println!("{msg}");
}
  1. p ← (empty)

    15fn main() {16    let → (empty)p = Person { name: String::from("Ada") };17    let msg = p.hello();18    println!("{msg}");
  2. msg ← "Hi, Ada"

    16    let p = Person { name: String::from("Ada") };17    let ms→ "Hi, Ada"g = p.hello();18    println!("{msg}");19}
    outputHi, Ada

Follow the Trait Call

  1. p is a Person with name Ada.
  2. p.hello() calls the Greet behavior implemented for Person.
  3. Inside the method, self.name is Ada.
  4. format!("Hi, {}", self.name) returns Hi, Ada.
  5. msg stores that text and the program prints Hi, Ada. | step | value | | --- | --- | | p | Person { name: "Ada" } | | self.name | Ada | | return value | Hi, Ada | | stdout | Hi, Ada |
trait `trait Greet` declares required methods.
impl Trait for Type `impl Greet for Person` provides the behavior.
method call `p.hello()` runs the implemented method.

Exercise: traits.rs

Reproduce the output Hi, Ada, then trace how p.hello() reads self.name as Ada and returns Hi, Ada.