diff --git a/doc/tutorial.md b/doc/tutorial.md index a0fa95d31be..b9ad8900a4f 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -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