Change iface and interface to trait. Close #2967.
This commit is contained in:
parent
7c1339b2f1
commit
0b3dba42cf
@ -34,8 +34,9 @@ high-level features include:
|
||||
* ***Higher-order functions.*** Rust functions may take closures as
|
||||
arguments or return closures as return values. Closures in Rust are
|
||||
very powerful and used pervasively.
|
||||
* ***Interface polymorphism.*** Rust's type system features a unique
|
||||
combination of Java-style interfaces and Haskell-style typeclasses.
|
||||
* ***Trait polymorphism.*** Rust's type system features a unique
|
||||
combination of Java-style interfaces and Haskell-style typeclasses
|
||||
called _traits_.
|
||||
* ***Parametric polymorphism (generics).*** Functions and types can be
|
||||
parameterized over type variables with optional type constraints.
|
||||
* ***Type inference.*** Type annotations on local variable
|
||||
@ -2089,9 +2090,9 @@ resource type. Rust has several kinds that can be used as type bounds:
|
||||
mutable fields nor shared boxes.
|
||||
|
||||
> ***Note:*** Rust type kinds are syntactically very similar to
|
||||
> [interfaces](#interfaces) when used as type bounds, and can be
|
||||
> conveniently thought of as built-in interfaces. In the future type
|
||||
> kinds will actually be interfaces that the compiler has special
|
||||
> [traits](#traits) when used as type bounds, and can be
|
||||
> conveniently thought of as built-in traits. In the future type
|
||||
> kinds will actually be traits that the compiler has special
|
||||
> knowledge about.
|
||||
|
||||
## Generic functions and argument-passing
|
||||
@ -2388,9 +2389,9 @@ This makes it possible to rebind a variable without actually mutating
|
||||
it, which is mostly useful for destructuring (which can rebind, but
|
||||
not assign).
|
||||
|
||||
# Interfaces
|
||||
# Traits
|
||||
|
||||
Interfaces are Rust's take on value polymorphism—the thing that
|
||||
Traits are Rust's take on value polymorphism—the thing that
|
||||
object-oriented languages tend to solve with methods and inheritance.
|
||||
For example, writing a function that can operate on multiple types of
|
||||
collections.
|
||||
@ -2400,27 +2401,27 @@ collections.
|
||||
|
||||
## Declaration
|
||||
|
||||
An interface consists of a set of methods. A method is a function that
|
||||
A trait consists of a set of methods. A method is a function that
|
||||
can be applied to a `self` value and a number of arguments, using the
|
||||
dot notation: `self.foo(arg1, arg2)`.
|
||||
|
||||
For example, we could declare the interface `to_str` for things that
|
||||
For example, we could declare the trait `to_str` for things that
|
||||
can be converted to a string, with a single method of the same name:
|
||||
|
||||
~~~~
|
||||
iface to_str {
|
||||
trait to_str {
|
||||
fn to_str() -> ~str;
|
||||
}
|
||||
~~~~
|
||||
|
||||
## Implementation
|
||||
|
||||
To actually implement an interface for a given type, the `impl` form
|
||||
To actually implement an trait for a given type, the `impl` form
|
||||
is used. This defines implementations of `to_str` for the `int` and
|
||||
`~str` types.
|
||||
|
||||
~~~~
|
||||
# iface to_str { fn to_str() -> ~str; }
|
||||
# trait to_str { fn to_str() -> ~str; }
|
||||
impl of to_str for int {
|
||||
fn to_str() -> ~str { int::to_str(self, 10u) }
|
||||
}
|
||||
@ -2439,13 +2440,13 @@ method that matches the name, and simply calls that.
|
||||
|
||||
Implementations are not globally visible. Resolving a method to an
|
||||
implementation requires that implementation to be in scope. You can
|
||||
import and export implementations using the name of the interface they
|
||||
import and export implementations using the name of the trait they
|
||||
implement (multiple implementations with the same name can be in scope
|
||||
without problems). Or you can give them an explicit name if you
|
||||
prefer, using this syntax:
|
||||
|
||||
~~~~
|
||||
# iface to_str { fn to_str() -> ~str; }
|
||||
# trait to_str { fn to_str() -> ~str; }
|
||||
impl nil_to_str of to_str for () {
|
||||
fn to_str() -> ~str { ~"()" }
|
||||
}
|
||||
@ -2461,7 +2462,7 @@ known at compile time, it is possible to specify 'bounds' for type
|
||||
parameters.
|
||||
|
||||
~~~~
|
||||
# iface to_str { fn to_str() -> ~str; }
|
||||
# trait to_str { fn to_str() -> ~str; }
|
||||
fn comma_sep<T: to_str>(elts: ~[T]) -> ~str {
|
||||
let mut result = ~"", first = true;
|
||||
for elts.each |elt| {
|
||||
@ -2476,18 +2477,18 @@ fn comma_sep<T: to_str>(elts: ~[T]) -> ~str {
|
||||
The syntax for this is similar to the syntax for specifying that a
|
||||
parameter type has to be copyable (which is, in principle, another
|
||||
kind of bound). By declaring `T` as conforming to the `to_str`
|
||||
interface, it becomes possible to call methods from that interface on
|
||||
trait, it becomes possible to call methods from that trait on
|
||||
values of that type inside the function. It will also cause a
|
||||
compile-time error when anyone tries to call `comma_sep` on an array
|
||||
whose element type does not have a `to_str` implementation in scope.
|
||||
|
||||
## Polymorphic interfaces
|
||||
## Polymorphic traits
|
||||
|
||||
Interfaces may contain type parameters. This defines an interface for
|
||||
Traits may contain type parameters. This defines a trait for
|
||||
generalized sequence types:
|
||||
|
||||
~~~~
|
||||
iface seq<T> {
|
||||
trait seq<T> {
|
||||
fn len() -> uint;
|
||||
fn iter(fn(T));
|
||||
}
|
||||
@ -2500,25 +2501,25 @@ impl <T> of seq<T> for ~[T] {
|
||||
~~~~
|
||||
|
||||
Note that the implementation has to explicitly declare the its
|
||||
parameter `T` before using it to specify its interface type. This is
|
||||
parameter `T` before using it to specify its trait type. This is
|
||||
needed because it could also, for example, specify an implementation
|
||||
of `seq<int>`—the `of` clause *refers* to a type, rather than defining
|
||||
one.
|
||||
|
||||
The type parameters bound by an iface are in scope in each of the
|
||||
The type parameters bound by a trait are in scope in each of the
|
||||
method declarations. So, re-declaring the type parameter
|
||||
`T` as an explicit type parameter for `len` -- in either the iface or
|
||||
`T` as an explicit type parameter for `len` -- in either the trait or
|
||||
the impl -- would be a compile-time error.
|
||||
|
||||
## The `self` type in interfaces
|
||||
## The `self` type in traits
|
||||
|
||||
In an interface, `self` is a special type that you can think of as a
|
||||
type parameter. An implementation of the interface for any given type
|
||||
In a trait, `self` is a special type that you can think of as a
|
||||
type parameter. An implementation of the trait for any given type
|
||||
`T` replaces the `self` type parameter with `T`. The following
|
||||
interface describes types that support an equality operation:
|
||||
trait describes types that support an equality operation:
|
||||
|
||||
~~~~
|
||||
iface eq {
|
||||
trait eq {
|
||||
fn equals(&&other: self) -> bool;
|
||||
}
|
||||
|
||||
@ -2530,15 +2531,15 @@ impl of eq for int {
|
||||
Notice that `equals` takes an `int` argument, rather than a `self` argument, in
|
||||
an implementation for type `int`.
|
||||
|
||||
## Casting to an interface type
|
||||
## Casting to an trait type
|
||||
|
||||
The above allows us to define functions that polymorphically act on
|
||||
values of *an* unknown type that conforms to a given interface.
|
||||
values of *an* unknown type that conforms to a given trait.
|
||||
However, consider this function:
|
||||
|
||||
~~~~
|
||||
# type circle = int; type rectangle = int;
|
||||
# iface drawable { fn draw(); }
|
||||
# trait drawable { fn draw(); }
|
||||
# impl of drawable for int { fn draw() {} }
|
||||
# fn new_circle() -> int { 1 }
|
||||
fn draw_all<T: drawable>(shapes: ~[T]) {
|
||||
@ -2549,14 +2550,14 @@ fn draw_all<T: drawable>(shapes: ~[T]) {
|
||||
~~~~
|
||||
|
||||
You can call that on an array of circles, or an array of squares
|
||||
(assuming those have suitable `drawable` interfaces defined), but not
|
||||
(assuming those have suitable `drawable` traits defined), but not
|
||||
on an array containing both circles and squares.
|
||||
|
||||
When this is needed, an interface name can be used as a type, causing
|
||||
When this is needed, a trait name can be used as a type, causing
|
||||
the function to be written simply like this:
|
||||
|
||||
~~~~
|
||||
# iface drawable { fn draw(); }
|
||||
# trait drawable { fn draw(); }
|
||||
fn draw_all(shapes: ~[drawable]) {
|
||||
for shapes.each |shape| { shape.draw(); }
|
||||
}
|
||||
@ -2571,11 +2572,11 @@ is very similar to the 'vtables' used in most object-oriented
|
||||
languages.
|
||||
|
||||
To construct such a value, you use the `as` operator to cast a value
|
||||
to an interface type:
|
||||
to a trait type:
|
||||
|
||||
~~~~
|
||||
# type circle = int; type rectangle = int;
|
||||
# iface drawable { fn draw(); }
|
||||
# trait drawable { fn draw(); }
|
||||
# impl of drawable for int { fn draw() {} }
|
||||
# fn new_circle() -> int { 1 }
|
||||
# fn new_rectangle() -> int { 2 }
|
||||
@ -2594,10 +2595,10 @@ Note that the allocation of a box is somewhat more expensive than
|
||||
simply using a type parameter and passing in the value as-is, and much
|
||||
more expensive than statically resolved method calls.
|
||||
|
||||
## Interface-less implementations
|
||||
## Trait-less implementations
|
||||
|
||||
If you only intend to use an implementation for static overloading,
|
||||
and there is no interface available that it conforms to, you are free
|
||||
and there is no trait available that it conforms to, you are free
|
||||
to leave off the `of` clause. However, this is only possible when you
|
||||
are defining an implementation in the same module as the receiver
|
||||
type, and the receiver type is a named type (i.e., an enum or a
|
||||
|
Loading…
Reference in New Issue
Block a user