Rust traits: Difference between revisions
No edit summary |
No edit summary |
||
Line 122: | Line 122: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Conditional Implementation --> | </blockquote><!-- Conditional Implementation --> | ||
= Builtin Traits = | |||
<blockquote> | |||
There are several builtin traits.<br> | |||
Some must be imported into scope for methods to be available (like refinements),<br> | |||
Others are applied automatically to objects.<br> | |||
These builtin traits are documented (non-exhaustively) in other sections. | |||
{| class="wikitable" | |||
|- | |||
| [[rust pointers]] | |||
|- | |||
| [[rust threading]] | |||
|- | |||
|} | |||
</blockquote><!-- Builtin Traits --> |
Latest revision as of 04:22, 11 February 2023
Traits are similar to interfaces with some key differences:
- they can have a default implementation.
- they can behave like refinements, only adding the method if the trait has been imported into namespace
Basics
NOTE:
If the trait method implementation is in a different file than your type,
you'll need to import the trait into the current namespace so it is usable on your object!
ex.std::io::BufRead
Define and implement trait
struct Cat { name: String } struct Dog { name: String, breed: String } // all implementors of 'Pet' must have method 'play' with this method signature trait Pet { fn play(&self) -> bool; } impl Pet for Cat { fn play(&self) -> bool { println!("you give a ball of yarn to {}", self.name); true } }Use trait implementors in method signature
// use trait as param type fn play_with_pet(pet: &impl Pet) -> bool { pet.play(); } let cat = Cat{name: "maize".to_string()}; let dog = Dog{name: "midnight".to_string(), breed: "?".to_string()}; play_with_pet(&cat); play_with_pet(&dog);
In Function Signatures
As Param
// with impl fn play_with_pet(pet: &impl Pet) -> bool {} // trait-bound-syntax (generic) fn play_with_pet<P: Pet>(pet: P) -> bool {}Requires object implements multiple interfaces
// with impl fn play_with_pet(pet: &(impl Pet + Display)) -> bool {} // with where clause fn play_with_pet<P>(p: P) -> bool where P: Pet + Display {}As Return
If you're only ever returning one possible concretion, you can do this:
fn gimme_pet() -> impl Pet { // ... }But if you may return different types of implementors of Pet, you'll need to do this: https://doc.rust-lang.org/stable/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
// TODO
Default Method Implementation
Unlike interfaces in most other languages, you can define a default method implementation on the trait.
TODO:
can you require fields as well? (in this case, name)
struct Cat { name: String } struct Dog { name: String, breed: String } trait Pet { fn play(&self) { println!("rub") } }
Blanket Implementations
You can write traits that are automatically applied all objects,
that implements another trait.
// every object that implements `Display` // will automagically be assigned this `to_string()` method. impl<T: Display> ToString for T { fn to_string(v: T) -> String { format!("{}", ) } }
Builtin Traits
There are several builtin traits.
Some must be imported into scope for methods to be available (like refinements),
Others are applied automatically to objects.
These builtin traits are documented (non-exhaustively) in other sections.
rust pointers rust threading