Default Trait Implementations
In this page:
Defining a Default Method
A trait method can include a body directly in the trait definition, and any type implementing the trait automatically gets that behavior unless it overrides it.
Example: Defining a Default Method
trait Summary {
fn summarize(&self) -> String {
String::from("(no summary available)")
}
}
struct Article;
impl Summary for Article {}
fn main() {
let a = Article;
println!("{}", a.summarize());
}
Login to try C/C++/Java/PHP code in the editor
Overriding a Default Method
A type implementing the trait can still provide its own version of a method that has a default, replacing the default behavior entirely for that type.
Example: Overriding a Default Method
trait Summary {
fn summarize(&self) -> String {
String::from("(no summary available)")
}
}
struct Post {
title: String,
}
impl Summary for Post {
fn summarize(&self) -> String {
format!("Post: {}", self.title)
}
}
fn main() {
let post = Post { title: String::from("Rust Traits") };
println!("{}", post.summarize());
}
Login to try C/C++/Java/PHP code in the editor
Default Methods Calling Required Methods
A default method can call another method of the same trait that has no default, relying on every implementing type to provide that required piece while reusing shared logic around it.
Example: Default Methods Calling Required Methods
trait Greeting {
fn name(&self) -> String;
fn greet(&self) -> String {
format!("Hello, {}!", self.name())
}
}
struct User {
username: String,
}
impl Greeting for User {
fn name(&self) -> String {
self.username.clone()
}
}
fn main() {
let u = User { username: String::from("kai") };
println!("{}", u.greet());
}
Login to try C/C++/Java/PHP code in the editor
Mixing Default and Overridden Methods
A trait can have several methods, some with defaults and some overridden by a given type, letting each implementer reuse convenient shared logic while customizing only what it needs.
Example: Mixing Default and Overridden Methods
trait Vehicle {
fn wheels(&self) -> u32 {
4
}
fn describe(&self) -> String {
format!("A vehicle with {} wheels", self.wheels())
}
}
struct Motorcycle;
impl Vehicle for Motorcycle {
fn wheels(&self) -> u32 {
2
}
}
fn main() {
let m = Motorcycle;
println!("{}", m.describe());
}
Login to try C/C++/Java/PHP code in the editor
- Assuming every trait method must be re-implemented by every type -- default implementations let you skip that when the default fits.
- Forgetting a default method can still call other required (non-default) methods of the same trait, relying on each implementer to provide those.
- Overriding a default method unintentionally by accidentally redefining it with a different signature.
- A trait method can provide a default body, which implementing types automatically inherit unless they override it.
- Types can still choose to override a default implementation with their own custom version.
- Default methods can call other methods of the same trait, even ones without a default, relying on each type to supply those.
- Default implementations reduce repetitive boilerplate across many types implementing the same trait.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: