Show impl<T>
This includes a new example with Rectangle, instead of reusing HasArea, because fn area would require the Mul trait, and the added complexity of that would be better left for the Operators and Overloading chapter. Squashed at reviewer's request: Move teaser for trait bounds to bottom
This commit is contained in:
parent
04badd6a97
commit
0e92165eaf
2 changed files with 76 additions and 5 deletions
|
@ -101,11 +101,6 @@ fn takes_two_things<T, U>(x: T, y: U) {
|
|||
}
|
||||
```
|
||||
|
||||
Generic functions are most useful with ‘trait bounds’, which we’ll cover in the
|
||||
[section on traits][traits].
|
||||
|
||||
[traits]: traits.html
|
||||
|
||||
## Generic structs
|
||||
|
||||
You can store a generic type in a `struct` as well:
|
||||
|
@ -122,3 +117,28 @@ let float_origin = Point { x: 0.0, y: 0.0 };
|
|||
|
||||
Similarly to functions, the `<T>` is where we declare the generic parameters,
|
||||
and we then use `x: T` in the type declaration, too.
|
||||
|
||||
When you want to add an implementation for the generic struct, you just
|
||||
declare the type parameter after the `impl`:
|
||||
|
||||
```rust
|
||||
# struct Point<T> {
|
||||
# x: T,
|
||||
# y: T,
|
||||
# }
|
||||
#
|
||||
impl<T> Point<T> {
|
||||
fn swap(&mut self) {
|
||||
std::mem::swap(&mut self.x, &mut self.y);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
So far you’ve seen generics that take absolutely any type. These are useful in
|
||||
many cases: you’ve already seen `Option<T>`, and later you’ll meet universal
|
||||
container types like [`Vec<T>`][Vec]. On the other hand, often you want to
|
||||
trade that flexibility for increased expressive power. Read about [trait
|
||||
bounds][traits] to see why and how.
|
||||
|
||||
[traits]: traits.html
|
||||
[Vec]: ../std/vec/struct.Vec.html
|
||||
|
|
|
@ -152,6 +152,57 @@ We get a compile-time error:
|
|||
error: the trait `HasArea` is not implemented for the type `_` [E0277]
|
||||
```
|
||||
|
||||
## Traits bounds for generic structs
|
||||
|
||||
Trait constraints also can apply to implementations for generic structs. Just
|
||||
append the constraint when you declare type parameters. Here is a new type
|
||||
type `Rectangle<T>` and its operation `is_square()`:
|
||||
|
||||
```rust
|
||||
struct Rectangle<T> {
|
||||
x: T,
|
||||
y: T,
|
||||
width: T,
|
||||
height: T,
|
||||
}
|
||||
|
||||
impl<T: PartialEq> Rectangle<T> {
|
||||
fn is_square(&self) -> bool {
|
||||
self.width == self.height
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut r = Rectangle {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 47,
|
||||
height: 47,
|
||||
};
|
||||
|
||||
assert!(r.is_square());
|
||||
|
||||
r.height = 42;
|
||||
assert!(!r.is_square());
|
||||
}
|
||||
```
|
||||
|
||||
`is_square()` needs to check that the sides are equal, so the sides must be of
|
||||
a type that implements the [`core::cmp::PartialEq`][PartialEq] trait:
|
||||
|
||||
```ignore
|
||||
impl<T: PartialEq> Rectangle<T> { ... }
|
||||
```
|
||||
|
||||
Now, a rectangle can be defined in terms of any type that can be compared for
|
||||
equality.
|
||||
|
||||
[PartialEq]: ../core/cmp/trait.PartialEq.html
|
||||
|
||||
|
||||
|
||||
# Rules for implementing traits
|
||||
|
||||
So far, we’ve only added trait implementations to structs, but you can
|
||||
implement a trait for any type. So technically, we _could_ implement `HasArea`
|
||||
for `i32`:
|
||||
|
|
Loading…
Reference in a new issue