Menu
Coddy logo textTech

The Display Trait

Part of the Object Oriented Programming section of Coddy's Rust journey — lesson 36 of 61.

While Debug is great for developers inspecting data, the Display trait is designed for user-facing output. It's what powers the {} formatter in println!. Unlike Debug, Rust cannot automatically derive Display—you must implement it manually.

To implement Display, you need to bring in the fmt module and implement the fmt method:

use std::fmt;

struct Temperature {
    celsius: f64,
}

impl fmt::Display for Temperature {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}°C", self.celsius)
    }
}

The fmt method receives a Formatter and returns a fmt::Result. You use the write! macro to format your output, accessing the struct's fields through self.

Now you can print the struct with the standard {} formatter:

let temp = Temperature { celsius: 23.5 };
println!("{}", temp);  // 23.5°C

The key difference: Debug output shows the structure of your data (useful for debugging), while Display output is polished and meant for end users. A struct can implement both—use {:?} for debugging and {} for clean output.

challenge icon

Challenge

Easy

Let's create a user-friendly product display system! While Debug shows the raw structure of your data, the Display trait lets you craft polished, human-readable output perfect for end users.

You'll organize your code across two files:

  • product.rs: Define a public Product struct with two public fields: name (String) and price (f64). Implement the Display trait for your struct so it formats as {name} - ${price}. Remember to bring in std::fmt and use the write! macro inside your fmt method.
  • main.rs: Bring in your product module and create a Product instance using the inputs provided. Print the product using the standard {} formatter to show your custom display output.

The Display trait requires you to implement the fmt method manually—Rust can't derive it automatically like Debug. This gives you complete control over how your type appears to users.

Your output should display the product in a clean, user-friendly format:

{name} - ${price}

For example, with inputs Wireless Mouse and 29.99:

Wireless Mouse - $29.99

You will receive two inputs: the product name and the price (parse as f64).

Cheat sheet

The Display trait is designed for user-facing output and powers the {} formatter in println!. Unlike Debug, it must be implemented manually.

To implement Display, bring in the fmt module and implement the fmt method:

use std::fmt;

struct Temperature {
    celsius: f64,
}

impl fmt::Display for Temperature {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}°C", self.celsius)
    }
}

The fmt method receives a Formatter and returns a fmt::Result. Use the write! macro to format output, accessing struct fields through self.

Print the struct with the {} formatter:

let temp = Temperature { celsius: 23.5 };
println!("{}", temp);  // 23.5°C

Key difference: Debug ({:?}) shows data structure for debugging, while Display ({}) provides polished output for end users.

Try it yourself

mod product;

use product::Product;

fn main() {
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();

    let mut price_input = String::new();
    std::io::stdin().read_line(&mut price_input).expect("Failed to read line");
    let price: f64 = price_input.trim().parse().expect("Failed to parse price");

    // TODO: Create a Product instance with the name and price

    // TODO: Print the product using the {} formatter
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming