Generic Traits
Traits can also be generic, just like types and functions. A trait’s parameters get concrete types when it is used.
1. ```
#[derive(Debug)]
```
2. ```
struct Foo(String);
```
4. ```
impl From<u32> for Foo {
```
5. ```
fn from(from: u32) -> Foo {
```
6. ```
Foo(format!("Converted from integer: {from}"))
```
7. ```
}
```
8. ```
}
```
10. ```
impl From<bool> for Foo {
```
11. ```
fn from(from: bool) -> Foo {
```
12. ```
Foo(format!("Converted from bool: {from}"))
```
13. ```
}
```
14. ```
}
```
16. ```
fn main() {
```
17. ```
let from_int = Foo::from(123);
```
18. ```
let from_bool = Foo::from(true);
```
19. ```
println!("{from_int:?}, {from_bool:?}");
```
20. ```
}
```
- The
Fromtrait will be covered later in the course, but its definition in the std docs is simple. - Implementations of the trait do not need to cover all possible type parameters. Here,
Foo::from("hello")would not compile because there is noFrom<&str>implementation forFoo. - Generic traits take types as “input”, while associated types are a kind of “output” type. A trait can have multiple implementations for different input types.
- In fact, Rust requires that at most one implementation of a trait match for any type T. Unlike some other languages, Rust has no heuristic for choosing the “most specific” match. There is work on adding this support, called specialization.
