f0a67d67c4fb7ef27e18b793e3c618b046d68400
[nit.git] / doc / manual / method.md
1 # Methods
2
3 `fun` declares methods. Methods must have a name, may have parameters, and may have a return type. Parameters are typed; however, a single type can be used for multiple parameters.
4
5 ~~~
6 fun foo(x, y: Int, s: String): Bool ...
7 ~~~
8
9 `do` declares the body of methods. Alike control structures, a one-liner version is available.
10 Therefore, the two following methods are equivalent.
11
12 ~~~
13 fun next1(i: Int): Int
14 do
15     return i + 1
16 end
17
18 fun next2(i: Int): Int do return i + 1
19 ~~~
20
21 Inside the method body, parameters are considered as variables. They can be assigned and are subject to adaptive typing.
22
23 `self`, the current receiver, is a special parameter. It is not assignable but is subject to adaptive typing.
24
25 `return` exits the method and returns to the caller. In a function, the return value must be provided with a return in all control flow paths.
26
27 ## Method Call
28
29 Calling a method is usually done with the dotted notation `x.foo(y, z)`. The dotted notation can be chained.
30
31 A method call with no argument does not need parentheses. Moreover, even with arguments, the parentheses are not required in the principal method of a statement.
32
33 ~~~
34 var a = [1]
35 a.add 5 # no () for add
36 print a.length # no () for length, no () for print
37 ~~~
38
39 However, this last facility requires that the first argument does not start with a parenthesis or a bracket.
40
41 ~~~
42 foo (x).bar # will be interpreted as (foo(x)).bar
43 foo [x].bar # will be interpreted as (foo[x]).bar
44 ~~~
45
46 ## Method Redefinition
47
48 `redef` denotes methods that are redefined in subclasses or in class refinements. The number and the types of the parameters must be invariant. Thus, there is no need to reprecise the types of the parameters, only names are mandatory.
49
50 The return type can be redefined to be a more precise type. If same type is returned, there is no need to reprecise it.
51
52 The visibility, also, cannot be changed, thus there is also no need to reprecise it.
53
54 ~~~
55 class Foo
56     # implicitly an Object
57     # therefore inherit '==' and 'to_s'
58     var i: Int
59     redef fun to_s do return "Foo{self.i}"
60     redef fun ==(f) do return f isa Foo and f.i == self.i
61 end
62 ~~~
63
64 ## Abstract Methods
65
66 `is abstract` indicates methods defined without a body. Subclasses and refinements can then redefine it (the `redef` is still mandatory) with a proper body.
67
68 ~~~
69 interface Foo
70     fun derp(x: Int): Int is abstract
71 end
72 class Bar
73     super Foo
74     redef fun derp(x) do return x + 1
75 end
76 ~~~
77
78 Concrete classes may have abstract methods. It is up to a refinement to provide a body.
79
80 ## Call to Super
81
82 `super` calls the “previous” definition of the method. It is used in a redefinition of a method in a subclass or in a refinement, It can be used with or without arguments; in the latter case, the original arguments are implicitly used.
83
84 The `super` of Nit behave more like the `call-next-method` of CLOS that the `super` of Java or Smalltalk. It permits the traversal of complex class hierarchies and refinement. Basically, `super` is polymorphic: the method called by `super` is not only determined by the class of
85 definition of the method but also by the dynamic type of `self`.
86
87 The principle it to produce a strict order of the redefinitions of a method (the linearization). Each call to `super` call the next method definition in the linearization. From a technical point of view, the linearization algorithm used is based on C3. It ensures that:
88
89 -   A definition comes after its redefinition.
90
91 -   A redefinition in a refinement comes before a redefnition in its superclass.
92
93 -   The order of the declaration of the superclasses is used as the
94     ultimate disambiguation.
95
96 <!-- -->
97
98 ~~~
99 class A
100     fun derp: String do return "A"
101 end
102 class B
103     super A
104     redef fun derp do return "B" + super
105 end
106 class C
107     super A
108     redef fun derp do return "C" + super
109 end
110 class D
111     super B
112     super C
113     redef fun derp do return "D" + super
114     # Here the linearization order of the class D is DBCA
115     # D before B because D specializes B
116     # B before A because B specializes A
117     # D before C because D specializes C
118     # C before A because C specializes A
119     # B before C because in D 'super B' is before 'super C'
120 end
121 var b = new B
122 print b.derp # outputs "BA"
123 var d = new D
124 print d.derp # outputs "DBCA"
125 ~~~
126
127 ## Operators and Setters
128
129 Operators and setters are methods that require a special syntax for their definition and their invocation.
130
131 -   binary operators: `+`, `-`, `*`, `/`, `\%`, `==`, `<`, `>`, `<=`,`>=`, `<<`, `>>` and `<=>`. Their definitions require exactly one     parameter and a return value. Their invocation is done with `x + y` where `x` is the receiver, `+` is the operator, and `y` is the argument.
132
133 -   unary operator: `-`. Its definition requires a return value but no parameter. Its invocation is done with `-x` where `x` is the receiver.
134
135 -   bracket operator: `[]`. Its definition requires one parameter or more and a return value. Its invocation is done with `x[y, z]` where `x` is the receiver, `y` the first argument and `z` the second argument.
136
137 -   setters: `something=` where `something` can be any valid method identifier. Their definitions require one parameter or more and no return value. If there is only one parameter, the invocation is done with `x.something = y` where `x` is the receiver and y the argument. If there is more that one parameter, the invocation is done with `x.something(y, z) = t` where `x` is the receiver, `y` the first argument, `z` the second argument and `t` the last argument.
138
139 -   bracket setter: `[]=`. Its definition requires two parameters or more and no return value. Its invocation is done with `x[y, z] = t` where `x` is the receiver, `y` the first argument, `z` the second argument and `t` the last argument.
140
141 <!-- -->
142
143 ~~~
144 class Foo
145     fun +(a: Bar): Baz do ...
146     fun -: Baz do ...
147     fun [](a: Bar): Baz do ...
148     fun derp(a: Bar): Baz do ...
149     fun derp=(a: Bar, b: Baz) do ...
150     fun []= (a: Bar, b: Baz) do ...
151 end
152 var a: Foo = ...
153 var b: Bar = ...
154 var c: Baz = ...
155 c = a + b
156 c = -b
157 c = a[b] # The bracket operator '[]'
158 c = a.derp(b) # A normal method 'derp'
159 a.derp(b) = c # A setter 'derp='
160 a[b] = c # The bracket setter '[]='
161 ~~~
162
163 `+=` and `-=` are combinations of the assignment (`=`) and a binary operator. These feature are extended to setters where a single `+=` is in fact three method calls: a function call, the operator call, then a setter call.
164
165 ~~~
166 a += c # equiv. a = a + c
167 a[b] += c # equiv. a[b] = a[b] + c
168 a.foo += c # equiv. a.foo = a.foo + c
169 a.bar(b) += c # equiv. a.bar(b) = a.bar(b) + c
170 ~~~
171
172 ## Variable Number of Arguments
173
174 A method can accept a variable number of arguments using ellipsis (`...`). The definition use `x: Foo...` where `x` is the name of the parameter and `Foo` a type. Inside the body, the static type of `x` is `Array[Foo]`. The caller can use 0, 1, or more arguments for the parameter `x`. Only one ellipsis is allowed in a signature.
175
176 ~~~
177 fun foo(x: Int, y: Int..., z: Int)
178 do
179     print "{x};{y.join(",")};{z}"
180 end
181 foo(1, 2, 3, 4, 5) # outputs "1;2,3,4;5"
182 foo(1, 2, 3) # outputs "1;2;3"
183 ~~~
184
185 ## Top-level Methods and Main Body
186
187 Some functions, like `print`, are usable everywhere simply without using a specific receiver. Such methods are just defined outside any classes. In fact, these methods are implicitly defined in the
188 `Object` interface, therefore inherited by all classes, therefore usable everywhere. However, this principle may change in a future version.
189
190 In a module, the main body is a bunch of statements at the end of a file. The main body of the main module is the program entry point. In fact, the main method of a program is implicitly defined as the redefinition of the method `main` of the `Sys` class; and the start of the program is the implicit statement `(Sys.new).main`. Note that because it is a redefinition, the main part can use `super` to call the “previous” main part in the imported modules. If there is no main part
191 in a module, it is inherited from imported modules.
192
193 Top-level methods coupled with the main body can be used to program in a pseudo-procedural way. Therefore, the following programs are valid:
194
195 ~~~
196 print "Hello World!"
197 ~~~
198
199 ~~~
200 fun sum(i, j: Int): Int
201 do
202     return i + j
203 end
204 print sum(4, 5)
205 ~~~
206
207 ## Intern and Extern Methods
208
209 `intern` and `extern` indicate concrete methods whose body is not written in Nit.
210
211 The body of `intern` methods is provided by the compiler itself for performance or bootstrap reasons. For the same reasons, some intern methods, like `+` in `Int` are not redefinable.
212
213 The body of `extern` methods is provided by libraries written in C; for instance, the system libraries required for input/output. Extern methods are always redefinable. See [[FFI]] for more information on `extern` methods.