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
EasyLet'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 publicProductstruct with two public fields:name(String) andprice(f64). Implement theDisplaytrait for your struct so it formats as{name} - ${price}. Remember to bring instd::fmtand use thewrite!macro inside yourfmtmethod.main.rs: Bring in your product module and create aProductinstance 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.99You 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
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Methods and Behavior
Intro Implementation BlocksThe Self ParameterMutable MethodsAssociated FunctionsMultiple Implementation BlocksMethod ChainingRecap - Rectangle Actions4Project: Virtual Pet
Defining the PetFeeding the Pet7Standard Traits
The Debug TraitThe Display TraitClone and CopyEquality TraitsRecap - Printable Point10Project: Document System
The Draw TraitText Component2Encapsulation and Modules
Modules BasicsThe Public KeywordPrivate FieldsGettersSettersRecap - Secure Locker5Generics
Generic StructsGeneric MethodsMultiple Generic TypesGeneric FunctionsRecap - Coordinate Point8Traits as Bounds
Trait Bounds SyntaxMultiple BoundsThe Where ClauseReturning Types with TraitsRecap - Generic Printer11Design Patterns in Rust
Newtype PatternCompositionThe Drop TraitFrom and IntoRecap - Smart Pointer Mock