3 Constructors in Nit behave differently.
5 Their objective is double :
7 * be compatible with full multiple-inheritance
8 * be simple enough to be KISS and compatible with the principle of least surprise.
11 ## `new` construction and simple classes
13 Classes in OO models are often a simple aggregates of attributes and methods.
15 By default, the `new` construction require a value for each attribute defined in a class without a default value.
20 var description: String
23 var p = new Product("ABC", "Bla bla", 15.95)
27 In subclasses, additional attributes are automatically collected.
35 var book = new Book("ABC", "Bla bla", 15.95, "John Doe")
39 ## special `init` method
41 The special init method is automatically invoked after the end of a `new` construction.
42 It is used to perform additional systematic tasks.
44 Because the `init` is run at the end of the initialization sequence, initialized attributes are usable in the body.
47 class OverpricedProduct
54 var op = new OverpricedProduct("ABC", "Bla bla", 15.95)
55 assert op.price == 159.50
59 ## Uncollected attributes
61 There is three cases for an attributes to not be collected in the `new`.
63 * Attributes with a default value
64 * Attributes with the annotation `noinit`
65 * Attributes introduced in refinement of classes
71 var total_price: Float is noinit
74 total_price = price * (1.0 + tax_rate/100.0)
77 var tp = new TaxedProduct("ABC", "Bla bla", 15.95)
78 assert tp.total_price == 17.52905
81 Note: The orchestration here is important. In order, the following is executed:
83 1. All defauts values are computed and set
84 2. Setters are invoked.
87 Therefore, `total_price` cannot be initialised with a default value, because at the time of the computation of the default values, the attribute `price` in not yet initialised.
90 ## Generalized initializers
92 Initializers are methods that are automatically invoked by the new.
93 In fact, by default, the setter of an attribute is used as a initializer.
95 `autoinit` is used to register a method as a setter.
100 fun set_xy(x, y: Int) is autoinit do z = x * 10 + y
103 var fp = new FooProduct("ABC", "Bla bla", 15.96, 1, 3)
107 Generalized setters are a powerful tool but often needed in only rare specific cases.
108 In most case, there is no reason that an argument of a `new` construction is not stored in the object as a real attribute.
113 As explained above, one of the main advantage of these constructors is their compatibility with multiple inheritance.
117 super OverpricedProduct
121 var mp = new MultiProduct("ABC", "Bla bla", 15.96, 1, 3)
122 assert mp.id == "ABC"
123 assert mp.price == 159.6
124 assert mp.total_price == 175.4
131 Named `init` are less flexible trough inheritance, thus should no be used.
132 They allow to have additional constructor for classes and more control in the construction mechanism.
144 init polar(r, phi: Float)
151 redef fun to_s do return "({x},{y})"
153 var p1 = new Point(1.0, 2.0)
154 assert p1.to_s == "(1,2)"
155 var p2 = new Point.origin
156 assert p2.to_s == "(0,0)"
157 var p3 = new Point.polar(1.0, 2.0)
158 assert p3.to_s == "(-0.4161,0.9092)"
164 nameless `init` defined with argument or with an explicit visibility are still accepted as a fallback of the old-constructors.
165 They should not be used since they will be removed in a near future.
170 `new` factories permit to completely shortcut the class instantiation mechanim.
171 It could be used to provide `new` syntax on non-concrete class (mainly `extern class`).
173 `new` factories behave like a top-level function that return the result of the construction.
174 It is basically some kind of syntactic sugar.
177 abstract class Person
182 return new Adult(age)
184 return new Child(age)