@@ -47,8 +47,11 @@ As you can see, the `trait` block looks very similar to the `impl` block,
4747but we don’t define a body, just a type signature. When we ` impl ` a trait,
4848we use ` impl Trait for Item ` , rather than just ` impl Item ` .
4949
50- We can use traits to constrain our generics. Consider this function, which
51- does not compile:
50+ ## Traits bounds for generic functions
51+
52+ Traits are useful because they allow a type to make certain promises about its
53+ behavior. Generic functions can exploit this to constrain the types they
54+ accept. Consider this function, which does not compile:
5255
5356``` rust,ignore
5457fn print_area<T>(shape: T) {
@@ -75,7 +78,7 @@ fn print_area<T: HasArea>(shape: T) {
7578}
7679```
7780
78- The syntax ` <T: HasArea> ` means ` any type that implements the HasArea trait ` .
81+ The syntax ` <T: HasArea> ` means “ any type that implements the ` HasArea ` trait.”
7982Because traits define function type signatures, we can be sure that any type
8083which implements ` HasArea ` will have an ` .area() ` method.
8184
@@ -152,6 +155,63 @@ We get a compile-time error:
152155error: the trait `HasArea` is not implemented for the type `_` [E0277]
153156```
154157
158+ ## Traits bounds for generic structs
159+
160+ Your generic structs can also benefit from trait constraints. All you need to
161+ do is append the constraint when you declare type parameters. Here is a new
162+ type ` Rectangle<T> ` and its operation ` is_square() ` :
163+
164+ ``` rust
165+ struct Rectangle <T > {
166+ x : T ,
167+ y : T ,
168+ width : T ,
169+ height : T ,
170+ }
171+
172+ impl <T : PartialEq > Rectangle <T > {
173+ fn is_square (& self ) -> bool {
174+ self . width == self . height
175+ }
176+ }
177+
178+ fn main () {
179+ let mut r = Rectangle {
180+ x : 0 ,
181+ y : 0 ,
182+ width : 47 ,
183+ height : 47 ,
184+ };
185+
186+ assert! (r . is_square ());
187+
188+ r . height = 42 ;
189+ assert! (! r . is_square ());
190+ }
191+ ```
192+
193+ ` is_square() ` needs to check that the sides are equal, so the sides must be of
194+ a type that implements the [ ` core::cmp::PartialEq ` ] [ PartialEq ] trait:
195+
196+ ``` ignore
197+ impl<T: PartialEq> Rectangle<T> { ... }
198+ ```
199+
200+ Now, a rectangle can be defined in terms of any type that can be compared for
201+ equality.
202+
203+ [ PartialEq ] : ../core/cmp/trait.PartialEq.html
204+
205+ Here we defined a new struct ` Rectangle ` that accepts numbers of any
206+ precision—really, objects of pretty much any type—as long as they can be
207+ compared for equality. Could we do the same for our ` HasArea ` structs, ` Square `
208+ and ` Circle ` ? Yes, but they need multiplication, and to work with that we need
209+ to know more about [ operator traits] [ operators-and-overloading ] .
210+
211+ [ operators-and-overloading ] : operators-and-overloading.html
212+
213+ # Rules for implementing traits
214+
155215So far, we’ve only added trait implementations to structs, but you can
156216implement a trait for any type. So technically, we _ could_ implement ` HasArea `
157217for ` i32 ` :
@@ -175,7 +235,7 @@ impl HasArea for i32 {
175235It is considered poor style to implement methods on such primitive types, even
176236though it is possible.
177237
178- This may seem like the Wild West, but there are two other restrictions around
238+ This may seem like the Wild West, but there are two restrictions around
179239implementing traits that prevent this from getting out of hand. The first is
180240that if the trait isn’t defined in your scope, it doesn’t apply. Here’s an
181241example: the standard library provides a [ ` Write ` ] [ write ] trait which adds
@@ -340,10 +400,10 @@ This shows off the additional feature of `where` clauses: they allow bounds
340400where the left-hand side is an arbitrary type (` i32 ` in this case), not just a
341401plain type parameter (like ` T ` ).
342402
343- ## Default methods
403+ # Default methods
344404
345- There’s one last feature of traits we should cover: default methods. It’s
346- easiest just to show an example :
405+ If you already know how a typical implementor will define a method, you can
406+ let your trait supply a default :
347407
348408``` rust
349409trait Foo {
0 commit comments