Note that from an API point of view, there is no way to distinguish the read access of an attribute with a normal method neither to distinguish a write access of an attribute with a setter. Therefore, the read access of an attribute is called a getter while the write access is called a setter.
-~~~
+~~~nitish
var x = foo.bar # Is bar an attribute or a method?
foo.bar = y # Is bar an attribute or a setter?
# In fact, we do not need to know.
additional `writable` keyword.
~~~
-class Foo
- var pub_pri: X
- protected var pro_pri: X
- var pub_pub: X is writable
- private var pri_pro: X is protected writable
- var pub_pri2: X is private writable # the default
+class Foo2
+ var pub_pri: Int
+ protected var pro_pri: Int
+ var pub_pub: Int is writable
+ private var pri_pro: Int is protected writable
+ var pub_pri2: Int is private writable # the default
end
~~~
a redefinition while `redef writable` declares that the setter is a redefinition.
~~~
-interface Foo
+interface Foo3
fun derp: Int is abstract
fun derp=(o: Int) is abstract
end
-class Bar
- super Foo
- redef var derp: Int redef writable
+class Bar3
+ super Foo3
+ redef var derp is redef writable
end
-class Baz
- super Bar
- redef fun derp do ...
- redef fun derp=(o) do ...
+class Baz3
+ super Bar3
+ redef fun derp do return 1
+ redef fun derp=(o) do end
end
~~~
In subclasses, additional attributes are automatically collected.
~~~
+class Product
+ var id: String
+ var description: String
+ var price: Float
+end
class Book
super Product
var author: String
Because the `init` is run at the end of the initialization sequence, initialized attributes are usable in the body.
~~~
+class Product
+ var id: String
+ var description: String
+ var price: Float
+end
class OverpricedProduct
super Product
init
end
end
var op = new OverpricedProduct("ABC", "Bla bla", 15.95)
-assert op.price == 159.50
+assert op.price.is_approx(159.50, 0.001)
~~~
* Attributes introduced in refinement of classes
~~~
+class Product
+ var id: String
+ var description: String
+ var price: Float
+end
class TaxedProduct
super Product
var tax_rate = 9.90
end
end
var tp = new TaxedProduct("ABC", "Bla bla", 15.95)
-assert tp.total_price == 17.52905
+assert tp.total_price.is_approx(17.52905, 0.00001)
~~~
Note: The orchestration here is important. In order, the following is executed:
`autoinit` is used to register a method as a setter.
~~~
+class Product
+ var id: String
+ var description: String
+ var price: Float
+end
class FooProduct
super Product
fun set_xy(x, y: Int) is autoinit do z = x * 10 + y
As explained above, one of the main advantage of these constructors is their compatibility with multiple inheritance.
~~~
+class Product
+ var id: String
+ var description: String
+ var price: Float
+end
+class OverpricedProduct
+ super Product
+ init
+ do
+ price = price * 10.0
+ end
+end
+class TaxedProduct
+ super Product
+ var tax_rate = 9.90
+ var total_price: Float is noinit
+ init
+ do
+ total_price = price * (1.0 + tax_rate/100.0)
+ end
+end
+class FooProduct
+ super Product
+ fun set_xy(x, y: Int) is autoinit do z = x * 10 + y
+ var z: Int is noinit
+end
class MultiProduct
super OverpricedProduct
super TaxedProduct