Trait Basics
In this page:
Defining a Trait
The trait keyword defines a set of method signatures that any implementing type must provide, describing shared behavior without dictating how it's stored.
Example: Defining a Trait
trait Greet {
fn greet(&self) -> String;
}
struct Person {
name: String,
}
impl Greet for Person {
fn greet(&self) -> String {
format!("Hello, my name is {}", self.name)
}
}
fn main() {
let p = Person { name: String::from("Ada") };
println!("{}", p.greet());
}
Login to try C/C++/Java/PHP code in the editor
Implementing a Trait for Multiple Types
The same trait can be implemented for several unrelated types, each providing its own version of the required behavior.
Example: Implementing a Trait for Multiple Types
trait Greet {
fn greet(&self) -> String;
}
struct Robot;
impl Greet for Robot {
fn greet(&self) -> String {
String::from("BEEP BOOP HELLO")
}
}
fn main() {
let r = Robot;
println!("{}", r.greet());
}
Login to try C/C++/Java/PHP code in the editor
A Type Implementing Multiple Traits
A single type can implement as many different traits as needed, each contributing a different piece of behavior to that type.
Example: A Type Implementing Multiple Traits
trait Greet {
fn greet(&self) -> String;
}
trait Farewell {
fn farewell(&self) -> String;
}
struct Person {
name: String,
}
impl Greet for Person {
fn greet(&self) -> String {
format!("Hi, {}", self.name)
}
}
impl Farewell for Person {
fn farewell(&self) -> String {
format!("Bye, {}", self.name)
}
}
fn main() {
let p = Person { name: String::from("Lee") };
println!("{}", p.greet());
println!("{}", p.farewell());
}
Login to try C/C++/Java/PHP code in the editor
Calling Trait Methods Through the Trait
Once a trait is implemented for a type, its methods are called using ordinary dot syntax, exactly like any other method, as long as the trait is in scope.
Example: Calling Trait Methods Through the Trait
trait Area {
fn area(&self) -> f64;
}
struct Square {
side: f64,
}
impl Area for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn main() {
let sq = Square { side: 4.0 };
println!("Area: {}", sq.area());
}
Login to try C/C++/Java/PHP code in the editor
- Forgetting to bring a trait into scope with
usebefore calling its methods on a type, even if the impl exists elsewhere. - Confusing a trait definition with a struct -- traits describe shared behavior, they do not themselves hold data.
- Implementing a trait's method with a different signature than the trait declares, which fails to compile.
- A trait defines a set of method signatures that implementing types agree to provide.
impl TraitName for TypeName { ... }provides the actual behavior for a specific type.- A single type can implement multiple different traits.
- Traits enable shared behavior across otherwise unrelated types, similar to interfaces in other languages.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: