@@ -2035,28 +2035,30 @@ C++ templates.
20352035
20362036## Traits
20372037
2038- Within a generic function the operations available on generic types
2039- are very limited. After all, since the function doesn't know what
2040- types it is operating on, it can't safely modify or query their
2041- values. This is where _traits_ come into play. Traits are Rust's most
2042- powerful tool for writing polymorphic code. Java developers will see
2043- them as similar to Java interfaces, and Haskellers will notice their
2044- similarities to type classes. Rust's traits are a form of *bounded
2045- polymorphism*: a trait is a way of limiting the set of possible types
2046- that a type parameter could refer to.
2047-
2048- As motivation, let us consider copying in Rust.
2049- The `clone` method is not defined for all Rust types.
2050- One reason is user-defined destructors:
2051- copying a type that has a destructor
2052- could result in the destructor running multiple times.
2053- Therefore, types with destructors cannot be copied
2054- unless you explicitly implement `Clone` for them.
2038+ Within a generic function -- that is, a function parameterized by a
2039+ type parameter, say, `T` -- the operations we can do on arguments of
2040+ type `T` are quite limited. After all, since we don't know what type
2041+ `T` will be instantiated with, we can't safely modify or query values
2042+ of type `T`. This is where _traits_ come into play. Traits are Rust's
2043+ most powerful tool for writing polymorphic code. Java developers will
2044+ see them as similar to Java interfaces, and Haskellers will notice
2045+ their similarities to type classes. Rust's traits give us a way to
2046+ express *bounded polymorphism*: by limiting the set of possible types
2047+ that a type parameter could refer to, they expand the number of
2048+ operations we can safely perform on arguments of that type.
2049+
2050+ As motivation, let us consider copying of values in Rust. The `clone`
2051+ method is not defined for values of every type. One reason is
2052+ user-defined destructors: copying a value of a type that has a
2053+ destructor could result in the destructor running multiple times.
2054+ Therefore, values of types that have destructors cannot be copied
2055+ unless we explicitly implement `clone` for them.
20552056
20562057This complicates handling of generic functions.
2057- If you have a type parameter `T`, can you copy values of that type?
2058- In Rust, you can't,
2059- and if you try to run the following code the compiler will complain.
2058+ If we have a function with a type parameter `T`,
2059+ can we copy values of type `T` inside that function?
2060+ In Rust, we can't,
2061+ and if we try to run the following code the compiler will complain.
20602062
20612063~~~~ {.xfail-test}
20622064// This does not compile
@@ -2066,11 +2068,10 @@ fn head_bad<T>(v: &[T]) -> T {
20662068~~~~
20672069
20682070However, we can tell the compiler
2069- that the `head` function is only for copyable types:
2070- that is, those that implement the `Clone` trait.
2071- In that case,
2072- we can explicitly create a second copy of the value we are returning
2073- using the `clone` keyword:
2071+ that the `head` function is only for copyable types.
2072+ In Rust, copyable types are those that _implement the `Clone` trait_.
2073+ We can then explicitly create a second copy of the value we are returning
2074+ by calling the `clone` method:
20742075
20752076~~~~
20762077// This does
@@ -2079,12 +2080,14 @@ fn head<T: Clone>(v: &[T]) -> T {
20792080}
20802081~~~~
20812082
2082- This says that we can call `head` on any type `T`
2083- as long as that type implements the `Clone` trait.
2083+ The bounded type parameter `T: Clone` says that `head`
2084+ can be called on an argument of type `&[T]` for any `T`,
2085+ so long as there is an implementation of the
2086+ `Clone` trait for `T`.
20842087When instantiating a generic function,
2085- you can only instantiate it with types
2088+ we can only instantiate it with types
20862089that implement the correct trait,
2087- so you could not apply `head` to a type
2090+ so we could not apply `head` to a vector whose elements are of some type
20882091that does not implement `Clone`.
20892092
20902093While most traits can be defined and implemented by user code,
@@ -2110,7 +2113,7 @@ have the `'static` lifetime.
21102113> iterations of the language, and often still are.
21112114
21122115Additionally, the `Drop` trait is used to define destructors. This
2113- trait defines one method called `drop`, which is automatically
2116+ trait provides one method called `drop`, which is automatically
21142117called when a value of the type that implements this trait is
21152118destroyed, either because the value went out of scope or because the
21162119garbage collector reclaimed it.
@@ -2134,29 +2137,36 @@ may call it.
21342137
21352138## Declaring and implementing traits
21362139
2137- A trait consists of a set of methods without bodies,
2138- or may be empty, as is the case with `Send` and `Freeze`.
2140+ At its simplest, a trait is a set of zero or more _method signatures_.
21392141For example, we could declare the trait
21402142`Printable` for things that can be printed to the console,
2141- with a single method:
2143+ with a single method signature :
21422144
21432145~~~~
21442146trait Printable {
21452147 fn print(&self);
21462148}
21472149~~~~
21482150
2149- Traits may be implemented for specific types with [impls]. An impl
2150- that implements a trait includes the name of the trait at the start of
2151- the definition, as in the following impls of `Printable` for `int`
2152- and `~str`.
2151+ We say that the `Printable` trait _provides_ a `print` method with the
2152+ given signature. This means that we can call `print` on an argument
2153+ of any type that implements the `Printable` trait.
2154+
2155+ Rust's built-in `Send` and `Freeze` types are examples of traits that
2156+ don't provide any methods.
2157+
2158+ Traits may be implemented for specific types with [impls]. An impl for
2159+ a particular trait gives an implementation of the methods that
2160+ trait provides. For instance, the following impls of
2161+ `Printable` for `int` and `~str` give implementations of the `print`
2162+ method.
21532163
21542164[impls]: #methods
21552165
21562166~~~~
21572167# trait Printable { fn print(&self); }
21582168impl Printable for int {
2159- fn print(&self) { println!("{}", *self) }
2169+ fn print(&self) { println!("{:? }", *self) }
21602170}
21612171
21622172impl Printable for ~str {
@@ -2167,10 +2177,71 @@ impl Printable for ~str {
21672177# (~"foo").print();
21682178~~~~
21692179
2170- Methods defined in an implementation of a trait may be called just like
2171- any other method, using dot notation, as in `1.print()`. Traits may
2172- themselves contain type parameters. A trait for generalized sequence
2173- types might look like the following:
2180+ Methods defined in an impl for a trait may be called just like
2181+ any other method, using dot notation, as in `1.print()`.
2182+
2183+ ## Default method implementations in trait definitions
2184+
2185+ Sometimes, a method that a trait provides will have the same
2186+ implementation for most or all of the types that implement that trait.
2187+ For instance, suppose that we wanted `bool`s and `f32`s to be
2188+ printable, and that we wanted the implementation of `print` for those
2189+ types to be exactly as it is for `int`, above:
2190+
2191+ ~~~~
2192+ # trait Printable { fn print(&self); }
2193+ impl Printable for f32 {
2194+ fn print(&self) { println!("{:?}", *self) }
2195+ }
2196+
2197+ impl Printable for bool {
2198+ fn print(&self) { println!("{:?}", *self) }
2199+ }
2200+
2201+ # true.print();
2202+ # 3.14159.print();
2203+ ~~~~
2204+
2205+ This works fine, but we've now repeated the same definition of `print`
2206+ in three places. Instead of doing that, we can simply include the
2207+ definition of `print` right in the trait definition, instead of just
2208+ giving its signature. That is, we can write the following:
2209+
2210+ ~~~~
2211+ trait Printable {
2212+ // Default method implementation
2213+ fn print(&self) { println!("{:?}", *self) }
2214+ }
2215+
2216+ impl Printable for int {}
2217+
2218+ impl Printable for ~str {
2219+ fn print(&self) { println(*self) }
2220+ }
2221+
2222+ impl Printable for bool {}
2223+
2224+ impl Printable for f32 {}
2225+
2226+ # 1.print();
2227+ # (~"foo").print();
2228+ # true.print();
2229+ # 3.14159.print();
2230+ ~~~~
2231+
2232+ Here, the impls of `Printable` for `int`, `bool`, and `f32` don't
2233+ need to provide an implementation of `print`, because in the absence
2234+ of a specific implementation, Rust just uses the _default method_
2235+ provided in the trait definition. Depending on the trait, default
2236+ methods can save a great deal of boilerplate code from having to be
2237+ written in impls. Of course, individual impls can still override the
2238+ default method for `print`, as is being done above in the impl for
2239+ `~str`.
2240+
2241+ ## Type-parameterized traits
2242+
2243+ Traits may be parameterized by type variables. For example, a trait
2244+ for generalized sequence types might look like the following:
21742245
21752246~~~~
21762247trait Seq<T> {
@@ -3023,7 +3094,7 @@ they model most closely what people expect to shadow.
30233094
30243095## Package ids
30253096
3026- If you use ` extern mod ` , per default ` rustc ` will look for libraries in the the library search path (which you can
3097+ If you use ` extern mod ` , per default ` rustc ` will look for libraries in the library search path (which you can
30273098extend with the ` -L ` switch).
30283099
30293100However, Rust also ships with rustpkg, a package manager that is able to automatically download and build
0 commit comments