3 A _trait_ describes an abstract interface that types can implement. This
4 interface consists of [associated items], which come in three varieties:
6 - [functions](items/associated-items.html#associated-functions-and-methods)
7 - [types](items/associated-items.html#associated-types)
8 - [constants](items/associated-items.html#associated-constants)
10 All traits define an implicit type parameter `Self` that refers to "the type
11 that is implementing this interface". Traits may also contain additional type
12 parameters. These type parameters (including `Self`) may be constrained by
13 other traits and so forth as usual.
15 Traits are implemented for specific types through separate [implementations].
19 Generic functions may use traits as _bounds_ on their type parameters. This
20 will have three effects:
22 - Only types that have the trait may instantiate the parameter.
23 - Within the generic function, the methods of the trait can be called on values
24 that have the parameter's type. Associated types can be used in the
25 function's signature, and associated constants can be used in expressions
26 within the function body.
27 - Generic functions and types with the same or weaker bounds can use the
28 generic type in the function body or signature.
34 # trait Shape { fn draw(&self, Surface); }
35 struct Figure<S: Shape>(S, S);
36 fn draw_twice<T: Shape>(surface: Surface, sh: T) {
40 fn draw_figure<U: Shape>(surface: Surface, Figure(sh1, sh2): Figure<U>) {
42 draw_twice(surface, sh2); // Can call this since U: Shape
48 Type parameters can be specified for a trait to make it generic. These appear
49 after the trait name, using the same syntax used in [generic
50 functions](items/functions.html#generic-functions).
55 fn elt_at(&self, n: u32) -> T;
56 fn iter<F>(&self, F) where F: Fn(T);
62 Object safe traits can be the base trait of a [trait object]. A trait is
63 *object safe* if it has the following qualities (defined in [RFC 255]):
65 * It must not require `Self: Sized`
66 * All associated functions must either have a `where Self: Sized` bound or
67 * Not have any type parameters (although lifetime parameters are allowed)
68 * Must be a method: its first parameter must be called self, with type
69 `Self`, `&Self`, `&mut Self`, `Box<Self>`.
70 * `Self` may only be used in the type of the receiver.
71 * It must not have any associated constants.
75 Trait bounds on `Self` are considered "supertraits". These are required to be
76 acyclic. Supertraits are somewhat different from other constraints in that
77 they affect what methods are available in the vtable when the trait is used as
78 a [trait object]. Consider the following example:
81 trait Shape { fn area(&self) -> f64; }
82 trait Circle : Shape { fn radius(&self) -> f64; }
85 The syntax `Circle : Shape` means that types that implement `Circle` must also
86 have an implementation for `Shape`. Multiple supertraits are separated by `+`,
87 `trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a
88 given type `T`, methods can refer to `Shape` methods, since the typechecker
89 checks that any type with an implementation of `Circle` also has an
90 implementation of `Shape`:
95 trait Shape { fn area(&self) -> f64; }
96 trait Circle : Shape { fn radius(&self) -> f64; }
98 fn area(&self) -> f64 {
102 impl Circle for Foo {
103 fn radius(&self) -> f64 {
104 println!("calling area: {}", self.area());
114 In type-parameterized functions, methods of the supertrait may be called on
115 values of subtrait-bound type parameters. Referring to the previous example of
116 `trait Circle : Shape`:
119 # trait Shape { fn area(&self) -> f64; }
120 # trait Circle : Shape { fn radius(&self) -> f64; }
121 fn radius_times_area<T: Circle>(c: T) -> f64 {
122 // `c` is both a Circle and a Shape
123 c.radius() * c.area()
127 Likewise, supertrait methods may also be called on trait objects.
130 # trait Shape { fn area(&self) -> f64; }
131 # trait Circle : Shape { fn radius(&self) -> f64; }
132 # impl Shape for i32 { fn area(&self) -> f64 { 0.0 } }
133 # impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } }
134 # let mycircle = 0i32;
135 let mycircle = Box::new(mycircle) as Box<Circle>;
136 let nonsense = mycircle.radius() * mycircle.area();
139 [`Send`]: ../std/marker/trait.Send.html
140 [`Send`]: ../std/marker/trait.Sync.html
141 [`UnwindSafe`]: ../std/panic/trait.UnwindSafe.html
142 [`RefUnwindSafe`]: ../std/panic/trait.RefUnwindSafe.html
143 [trait object]: types.html#trait-objects
144 [explicit]: expressions/operator-expr.html#type-cast-expressions
145 [methods called]: expressions/method-call-expr.html
146 [RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
147 [associated items]: items/associated-items.html