Traits #
- Create functions that we want classes to duplicate (or redefine), but outside a super class
- Code gets injected into any existing structure (both custom types and standard ones)
- Trait methods do not need to be fully defined, can define stub methods/declarations
- Data is not inherited
Advantages:
- Code reuse: Can create trait with parametrized functions implemented differently for different traits
- Code hiding: All parts of a trait are exposed, but we can specify exactly which functions should be injected, so no accidental spillover
Example:
struct TeddyBear { name : String, };
struct RedTeddyBear { name : String, };
trait Roar {
fn roar(&self) {
println!("{} ROAR!!!", self.name);
}
}
impl TeddyBear {
fn sing(&self) {
println!("SONG!");
}
}
impl RedTeddyBear {
fn sing(&self) {
println!("RED SONG!");
}
}
impl Roar for TeddyBear {}
impl Roar for RedTeddyBear {
fn roar(&self) {
println!("RED ROAR!");
}
}
Standard Rust traits #
Copy
: New copy of an instance created instead of moving ownership when using=
Clone
: Returns a new copy of an instance when calling.clone()
Drop
: Will define destructor to be used for objects reaching end of scopeDisplay
: How to format a type, used byprintln!()
andformat!()
Debug
: Similar toDisplay
but not user-facingEq
: Defines equivalence-relation equality determination for objects of the same timePartialEq
: Defines partial equivalence-relation equality determination
Example:
#[derive(Clone/*,...,*/)] // this can try to get the Rust compiler to automatically define an implementation for Clone
struct Point {
x: u32,
y: u32,
}
impl Clone for Point {
fn clone(&self) -> Point {
Point {x: self.x, y: self.y}
}
}