提交 191b328f 编写于 作者: B Brian Anderson

tutorial: Move method discussion after closures, before generics

/cc: #4217
上级 af5cd341
......@@ -1480,145 +1480,6 @@ if favorite_crayon_name.len() > 5 {
}
~~~
# Methods
Methods are like functions except that they always begin with a special argument,
called `self`,
which has the type of the method's receiver. The
`self` argument is like `this` in C++ and many other languages.
Methods are called with dot notation, as in `my_vec.len()`.
_Implementations_, written with the `impl` keyword, can define
methods on most Rust types, including structs and enums.
As an example, let's define a `draw` method on our `Shape` enum.
~~~
# fn draw_circle(p: Point, f: float) { }
# fn draw_rectangle(p: Point, p: Point) { }
struct Point {
x: float,
y: float
}
enum Shape {
Circle(Point, float),
Rectangle(Point, Point)
}
impl Shape {
fn draw(&self) {
match *self {
Circle(p, f) => draw_circle(p, f),
Rectangle(p1, p2) => draw_rectangle(p1, p2)
}
}
}
let s = Circle(Point { x: 1f, y: 2f }, 3f);
s.draw();
~~~
This defines an _implementation_ for `Shape` containing a single
method, `draw`. In most respects the `draw` method is defined
like any other function, except for the name `self`.
The type of `self` is the type on which the method is implemented,
or a pointer thereof. As an argument it is written either `self`,
`&self`, `@self`, or `~self`.
A caller must in turn have a compatible pointer type to call the method.
~~~
# fn draw_circle(p: Point, f: float) { }
# fn draw_rectangle(p: Point, p: Point) { }
# struct Point { x: float, y: float }
# enum Shape {
# Circle(Point, float),
# Rectangle(Point, Point)
# }
impl Shape {
fn draw_borrowed(&self) { ... }
fn draw_managed(@self) { ... }
fn draw_owned(~self) { ... }
fn draw_value(self) { ... }
}
let s = Circle(Point { x: 1f, y: 2f }, 3f);
(@s).draw_managed();
(~s).draw_owned();
(&s).draw_borrowed();
s.draw_value();
~~~
Methods typically take a borrowed pointer self type,
so the compiler will go to great lengths to convert a callee
to a borrowed pointer.
~~~
# fn draw_circle(p: Point, f: float) { }
# fn draw_rectangle(p: Point, p: Point) { }
# struct Point { x: float, y: float }
# enum Shape {
# Circle(Point, float),
# Rectangle(Point, Point)
# }
# impl Shape {
# fn draw_borrowed(&self) { ... }
# fn draw_managed(@self) { ... }
# fn draw_owned(~self) { ... }
# fn draw_value(self) { ... }
# }
# let s = Circle(Point { x: 1f, y: 2f }, 3f);
// As with typical function arguments, managed and unique pointers
// are automatically converted to borrowed pointers
(@s).draw_borrowed();
(~s).draw_borrowed();
// Unlike typical function arguments, the self value will
// automatically be referenced ...
s.draw_borrowed();
// ... and dereferenced
(& &s).draw_borrowed();
// ... and dereferenced, and borrowed, and
(&@~s).draw_borrowed();
~~~
Implementations may also define _static_ methods,
which don't have an explicit `self` argument.
The `static` keyword distinguishes static methods from methods that have a `self`:
~~~~ {.xfail-test}
impl Circle {
fn area(&self) -> float { ... }
static fn new(area: float) -> Circle { ... }
}
~~~~
> ***Note***: In the future the `static` keyword will be removed and static methods
> will be distinguished solely by the presence or absence of the `self` argument.
> In the current langugage instance methods may also be declared without an explicit
> `self` argument, in which case `self` is an implicit reference.
> That form of method is deprecated.
Constructors are one common application for static methods, as in `new` above.
To call a static method, you have to prefix it with the type name and a double colon:
~~~~
# use float::consts::pi;
# use float::sqrt;
struct Circle { radius: float }
impl Circle {
static fn new(area: float) -> Circle { Circle { radius: sqrt(area / pi) } }
}
let c = Circle::new(42.5);
~~~~
We'll discuss implementations more in the context of [traits and
generics](#generics).
# Closures
Named functions, like those we've seen so far, may not refer to local
......@@ -1886,6 +1747,142 @@ fn contains(v: &[int], elt: int) -> bool {
> the keywords `break`, `loop`, and `return` work, in varying degree,
> with `while`, `loop`, `do`, and `for` constructs.
# Methods
Methods are like functions except that they always begin with a special argument,
called `self`,
which has the type of the method's receiver. The
`self` argument is like `this` in C++ and many other languages.
Methods are called with dot notation, as in `my_vec.len()`.
_Implementations_, written with the `impl` keyword, can define
methods on most Rust types, including structs and enums.
As an example, let's define a `draw` method on our `Shape` enum.
~~~
# fn draw_circle(p: Point, f: float) { }
# fn draw_rectangle(p: Point, p: Point) { }
struct Point {
x: float,
y: float
}
enum Shape {
Circle(Point, float),
Rectangle(Point, Point)
}
impl Shape {
fn draw(&self) {
match *self {
Circle(p, f) => draw_circle(p, f),
Rectangle(p1, p2) => draw_rectangle(p1, p2)
}
}
}
let s = Circle(Point { x: 1f, y: 2f }, 3f);
s.draw();
~~~
This defines an _implementation_ for `Shape` containing a single
method, `draw`. In most respects the `draw` method is defined
like any other function, except for the name `self`.
The type of `self` is the type on which the method is implemented,
or a pointer thereof. As an argument it is written either `self`,
`&self`, `@self`, or `~self`.
A caller must in turn have a compatible pointer type to call the method.
~~~
# fn draw_circle(p: Point, f: float) { }
# fn draw_rectangle(p: Point, p: Point) { }
# struct Point { x: float, y: float }
# enum Shape {
# Circle(Point, float),
# Rectangle(Point, Point)
# }
impl Shape {
fn draw_borrowed(&self) { ... }
fn draw_managed(@self) { ... }
fn draw_owned(~self) { ... }
fn draw_value(self) { ... }
}
let s = Circle(Point { x: 1f, y: 2f }, 3f);
(@s).draw_managed();
(~s).draw_owned();
(&s).draw_borrowed();
s.draw_value();
~~~
Methods typically take a borrowed pointer self type,
so the compiler will go to great lengths to convert a callee
to a borrowed pointer.
~~~
# fn draw_circle(p: Point, f: float) { }
# fn draw_rectangle(p: Point, p: Point) { }
# struct Point { x: float, y: float }
# enum Shape {
# Circle(Point, float),
# Rectangle(Point, Point)
# }
# impl Shape {
# fn draw_borrowed(&self) { ... }
# fn draw_managed(@self) { ... }
# fn draw_owned(~self) { ... }
# fn draw_value(self) { ... }
# }
# let s = Circle(Point { x: 1f, y: 2f }, 3f);
// As with typical function arguments, managed and unique pointers
// are automatically converted to borrowed pointers
(@s).draw_borrowed();
(~s).draw_borrowed();
// Unlike typical function arguments, the self value will
// automatically be referenced ...
s.draw_borrowed();
// ... and dereferenced
(& &s).draw_borrowed();
// ... and dereferenced, and borrowed, and
(&@~s).draw_borrowed();
~~~
Implementations may also define _static_ methods,
which don't have an explicit `self` argument.
The `static` keyword distinguishes static methods from methods that have a `self`:
~~~~ {.xfail-test}
impl Circle {
fn area(&self) -> float { ... }
static fn new(area: float) -> Circle { ... }
}
~~~~
> ***Note***: In the future the `static` keyword will be removed and static methods
> will be distinguished solely by the presence or absence of the `self` argument.
> In the current langugage instance methods may also be declared without an explicit
> `self` argument, in which case `self` is an implicit reference.
> That form of method is deprecated.
Constructors are one common application for static methods, as in `new` above.
To call a static method, you have to prefix it with the type name and a double colon:
~~~~
# use float::consts::pi;
# use float::sqrt;
struct Circle { radius: float }
impl Circle {
static fn new(area: float) -> Circle { Circle { radius: sqrt(area / pi) } }
}
let c = Circle::new(42.5);
~~~~
# Generics
Throughout this tutorial, we've been defining functions that act only
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册