Rust Same-Name Methods
Same-name methods are methods that share one name on one type. Each method comes from a different trait, or from the type itself.
Three methods, one name
Two traits may both define a method with the same name, and one type may implement both. A type may also have its own method with that same name:
impl Pilot for Human { fn fly(&self) { println!("This is your captain speaking."); } }
impl Wizard for Human { fn fly(&self) { println!("Up!"); } }
impl Human { fn fly(&self) { println!("*waving arms furiously*"); } }The short call picks the own method
Call value.fly() and Rust picks the method written directly on the type:
let person = Human;
person.fly();Name the trait to pick its version
Call Pilot::fly(&value) to pick a trait version: name the trait, and pass the value as the first input:
Pilot::fly(&person);
Wizard::fly(&person);A trait can require another trait first
trait OutlinePrint: Display is a supertrait. A type must implement Display before it may implement OutlinePrint, and OutlinePrint may use the methods of Display:
trait OutlinePrint: Display {}Associated functions need the full name
Associated functions have no self, so a trait name alone is not enough: Animal::baby_name() fails with error E0790. Use fully qualified syntax — <Dog as Animal>::baby_name() says the type and the trait together:
let name = <Dog as Animal>::baby_name();
println!("{}", name);Same name, different return types
Two traits may share a method name even with different return types, because each impl lives in its own block. Fully qualified syntax settles which one a call means:
trait AgeWidget { fn get(&self) -> u8; }
trait NameWidget { fn get(&self) -> String; }
struct Form;
impl AgeWidget for Form { fn get(&self) -> u8 { 42 } }
impl NameWidget for Form { fn get(&self) -> String { String::from("Ada") } }
let form = Form;
println!("{} {}", <Form as AgeWidget>::get(&form), <Form as NameWidget>::get(&form));Example
trait Pilot { fn fly(&self); }
trait Wizard { fn fly(&self); }
struct Human;
impl Pilot for Human { fn fly(&self) { println!("This is your captain speaking."); } }
impl Wizard for Human { fn fly(&self) { println!("Up!"); } }
impl Human { fn fly(&self) { println!("*waving arms furiously*"); } }
fn main() {
let person = Human;
Pilot::fly(&person);
Wizard::fly(&person);
person.fly();
}Key points
- If a type has no method of its own and two of its traits share a name, value.get() fails with a "multiple get found" error: neither trait wins by default
- Same-name methods share one name on one type, each from a different source.
In this example, Human has three fly methods: one from Pilot, one from Wizard, and one of its own. Pilot::fly(&person) names the trait, so the captain line prints. Wizard::fly(&person) prints Up!. Plain person.fly() picks the method written directly on Human, so the arm-waving line prints last.
Note
Fully qualified syntax <Type as Trait>::name(...) works for any call.
You only need it when the short form is ambiguous.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
How do you call the Wizard version of fly on a Human value?