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:
Leif Arne Storset 2015-07-19 13:22:39 +02:00
parent 04badd6a97
commit 0e92165eaf
2 changed files with 76 additions and 5 deletions

View file

@ -101,11 +101,6 @@ fn takes_two_things<T, U>(x: T, y: U) {
}
```
Generic functions are most useful with trait bounds, which well 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 youve seen generics that take absolutely any type. These are useful in
many cases: youve already seen `Option<T>`, and later youll 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

View file

@ -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, weve only added trait implementations to structs, but you can
implement a trait for any type. So technically, we _could_ implement `HasArea`
for `i32`: