Skip to content

Commit 171e6a1

Browse files
committed
tutorial: Rewrite method section to deal with explicit self
Has to be moved until after the pointer discussion. /cc: #4217
1 parent 7d2c2db commit 171e6a1

File tree

1 file changed

+110
-47
lines changed

1 file changed

+110
-47
lines changed

doc/tutorial.md

Lines changed: 110 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ match mytup {
918918
}
919919
~~~~
920920

921-
# Functions and methods
921+
# Functions
922922

923923
We've already seen several function definitions. Like all other static
924924
declarations, such as `type`, functions can be declared both at the
@@ -968,52 +968,6 @@ assert 8 == line(5, 3, 1);
968968
assert () == oops(5, 3, 1);
969969
~~~~
970970

971-
Methods are like functions, except that they have an implicit argument
972-
called `self`, which has the type that the method's receiver has. The
973-
`self` argument is like 'this' in C++. An expression with dot
974-
notation, as in `my_vec.len()`, denotes a method
975-
call. Implementations, written with the `impl` keyword, can define
976-
methods on most Rust types. As an example, let's define a `draw`
977-
method on our `Shape` enum.
978-
979-
~~~
980-
# fn draw_circle(p: Point, f: float) { }
981-
# fn draw_rectangle(p: Point, p: Point) { }
982-
struct Point {
983-
x: float,
984-
y: float
985-
}
986-
987-
enum Shape {
988-
Circle(Point, float),
989-
Rectangle(Point, Point)
990-
}
991-
992-
impl Shape {
993-
fn draw() {
994-
match self {
995-
Circle(p, f) => draw_circle(p, f),
996-
Rectangle(p1, p2) => draw_rectangle(p1, p2)
997-
}
998-
}
999-
}
1000-
1001-
let s = Circle(Point { x: 1f, y: 2f }, 3f);
1002-
s.draw();
1003-
~~~
1004-
1005-
This defines an _implementation_ for `Shape` containing a single
1006-
method, `draw`. In most respects the `draw` method is defined
1007-
like any other function, except for the name `self`. `self`
1008-
is a special value that is automatically in scope inside each method,
1009-
referring to the value being operated on. If we wanted we could add
1010-
additional methods to the same impl, or multiple impls for the same
1011-
type. We'll discuss methods more in the context of [traits and
1012-
generics](#generics).
1013-
1014-
> ***Note:*** In the future, the method definition syntax will change to
1015-
> require declaring the `self` type explicitly, as the first argument.
1016-
1017971
# The Rust memory model
1018972

1019973
At this junction, let's take a detour to explain the concepts involved
@@ -1526,6 +1480,115 @@ if favorite_crayon_name.len() > 5 {
15261480
}
15271481
~~~
15281482

1483+
# Methods
1484+
1485+
Methods are like functions except that they always begin with a special argument,
1486+
called `self`,
1487+
which has the type of the method's receiver. The
1488+
`self` argument is like `this` in C++ and many other languages.
1489+
Methods are called with dot notation, as in `my_vec.len()`.
1490+
1491+
_Implementations_, written with the `impl` keyword, can define
1492+
methods on most Rust types, including structs and enums.
1493+
As an example, let's define a `draw` method on our `Shape` enum.
1494+
1495+
~~~
1496+
# fn draw_circle(p: Point, f: float) { }
1497+
# fn draw_rectangle(p: Point, p: Point) { }
1498+
struct Point {
1499+
x: float,
1500+
y: float
1501+
}
1502+
1503+
enum Shape {
1504+
Circle(Point, float),
1505+
Rectangle(Point, Point)
1506+
}
1507+
1508+
impl Shape {
1509+
fn draw(&self) {
1510+
match *self {
1511+
Circle(p, f) => draw_circle(p, f),
1512+
Rectangle(p1, p2) => draw_rectangle(p1, p2)
1513+
}
1514+
}
1515+
}
1516+
1517+
let s = Circle(Point { x: 1f, y: 2f }, 3f);
1518+
s.draw();
1519+
~~~
1520+
1521+
This defines an _implementation_ for `Shape` containing a single
1522+
method, `draw`. In most respects the `draw` method is defined
1523+
like any other function, except for the name `self`.
1524+
1525+
The type of `self` is the type on which the method is implemented,
1526+
or a pointer thereof. As an argument it is written either `self`,
1527+
`&self`, `@self`, or `~self`.
1528+
A caller must in turn have a compatible pointer type to call the method.
1529+
1530+
~~~
1531+
# fn draw_circle(p: Point, f: float) { }
1532+
# fn draw_rectangle(p: Point, p: Point) { }
1533+
# struct Point { x: float, y: float }
1534+
# enum Shape {
1535+
# Circle(Point, float),
1536+
# Rectangle(Point, Point)
1537+
# }
1538+
impl Shape {
1539+
fn draw_borrowed(&self) { ... }
1540+
fn draw_managed(@self) { ... }
1541+
fn draw_owned(~self) { ... }
1542+
fn draw_value(self) { ... }
1543+
}
1544+
1545+
let s = Circle(Point { x: 1f, y: 2f }, 3f);
1546+
1547+
(@s).draw_managed();
1548+
(~s).draw_owned();
1549+
(&s).draw_borrowed();
1550+
s.draw_value();
1551+
~~~
1552+
1553+
Methods typically take a borrowed pointer self type,
1554+
so the compiler will go to great lengths to convert a callee
1555+
to a borrowed pointer.
1556+
1557+
~~~
1558+
# fn draw_circle(p: Point, f: float) { }
1559+
# fn draw_rectangle(p: Point, p: Point) { }
1560+
# struct Point { x: float, y: float }
1561+
# enum Shape {
1562+
# Circle(Point, float),
1563+
# Rectangle(Point, Point)
1564+
# }
1565+
# impl Shape {
1566+
# fn draw_borrowed(&self) { ... }
1567+
# fn draw_managed(@self) { ... }
1568+
# fn draw_owned(~self) { ... }
1569+
# fn draw_value(self) { ... }
1570+
# }
1571+
# let s = Circle(Point { x: 1f, y: 2f }, 3f);
1572+
// As with typical function arguments, managed and unique pointers
1573+
// are automatically converted to borrowed pointers
1574+
1575+
(@s).draw_borrowed();
1576+
(~s).draw_borrowed();
1577+
1578+
// Unlike typical function arguments, the self value will
1579+
// automatically be referenced ...
1580+
s.draw_borrowed();
1581+
1582+
// ... and dereferenced
1583+
(& &s).draw_borrowed();
1584+
1585+
// ... and dereferenced, and borrowed, and
1586+
(&@~s).draw_borrowed();
1587+
~~~
1588+
1589+
We'll discuss implementations more in the context of [traits and
1590+
generics](#generics).
1591+
15291592
# Closures
15301593

15311594
Named functions, like those we've seen so far, may not refer to local

0 commit comments

Comments
 (0)