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.
6 fun foo(x, y: Int, s: String): Bool ...
9 `do` declares the body of methods. Alike control structures, a one-liner version is available.
10 Therefore, the two following methods are equivalent.
13 fun next1(i: Int): Int
18 fun next2(i: Int): Int do return i + 1
21 Inside the method body, parameters are considered as variables. They can be assigned and are subject to adaptive typing.
23 `self`, the current receiver, is a special parameter. It is not assignable but is subject to adaptive typing.
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.
29 Calling a method is usually done with the dotted notation `x.foo(y, z)`. The dotted notation can be chained.
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.
35 a.add 5 # no () for add
36 print a.length # no () for length, no () for print
39 However, this last facility requires that the first argument does not start with a parenthesis or a bracket.
42 foo (x).bar # will be interpreted as (foo(x)).bar
43 foo [x].bar # will be interpreted as (foo[x]).bar
46 ## Method Redefinition
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.
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.
52 The visibility, also, cannot be changed, thus there is also no need to reprecise it.
56 # implicitly an Object
57 # therefore inherit '==' and 'to_s'
59 redef fun to_s do return "Foo{self.i}"
60 redef fun ==(f) do return f isa Foo and f.i == self.i
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.
70 fun derp(x: Int): Int is abstract
74 redef fun derp(x) do return x + 1
78 Concrete classes may have abstract methods. It is up to a refinement to provide a body.
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.
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`.
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:
89 - A definition comes after its redefinition.
91 - A redefinition in a refinement comes before a redefnition in its superclass.
93 - The order of the declaration of the superclasses is used as the
94 ultimate disambiguation.
100 fun derp: String do return "A"
104 redef fun derp do return "B" + super
108 redef fun derp do return "C" + super
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'
122 print b.derp # outputs "BA"
124 print d.derp # outputs "DBCA"
127 ## Operators and Setters
129 Operators and setters are methods that require a special syntax for their definition and their invocation.
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.
133 - unary operator: `-`. Its definition requires a return value but no parameter. Its invocation is done with `-x` where `x` is the receiver.
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.
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.
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.
145 fun +(a: Bar): 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 ...
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 '[]='
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.
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
172 ## Variable Number of Arguments
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.
177 fun foo(x: Int, y: Int..., z: Int)
179 print "{x};{y.join(",")};{z}"
181 foo(1, 2, 3, 4, 5) # outputs "1;2,3,4;5"
182 foo(1, 2, 3) # outputs "1;2;3"
185 ## Top-level Methods and Main Body
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.
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.
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:
200 fun sum(i, j: Int): Int
207 ## Intern and Extern Methods
209 `intern` and `extern` indicate concrete methods whose body is not written in Nit.
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.
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.