| 1 | """ |
|---|
| 2 | This program shows how to declare and use properties. |
|---|
| 3 | Property declarations always start with one of three keywords: |
|---|
| 4 | * pro |
|---|
| 5 | * get |
|---|
| 6 | * set |
|---|
| 7 | """ |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | class Person |
|---|
| 11 | |
|---|
| 12 | var _name as String |
|---|
| 13 | |
|---|
| 14 | cue init(name as String) |
|---|
| 15 | base.init |
|---|
| 16 | _name = name |
|---|
| 17 | |
|---|
| 18 | pro name as String |
|---|
| 19 | """ |
|---|
| 20 | The name of the person. Setting the name trims preceding and |
|---|
| 21 | trailing whitespace from the value. |
|---|
| 22 | """ |
|---|
| 23 | get |
|---|
| 24 | return _name |
|---|
| 25 | set |
|---|
| 26 | # `value` is an implicit argument in all property setters: |
|---|
| 27 | _name = value.trim |
|---|
| 28 | |
|---|
| 29 | def printName |
|---|
| 30 | print .name |
|---|
| 31 | |
|---|
| 32 | def sayHello |
|---|
| 33 | print 'Hi, my name is [.name]' |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | class Program |
|---|
| 37 | |
|---|
| 38 | def main |
|---|
| 39 | p = Person('chuck') |
|---|
| 40 | print p.name |
|---|
| 41 | assert p.name == 'chuck' |
|---|
| 42 | p.name = 'Chuck' |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | # Many properties just cover for an underlying variable. When that |
|---|
| 46 | # is the case, you can use a shortcut syntax. Later, you can |
|---|
| 47 | # change the property to the full form in order to add logic. |
|---|
| 48 | |
|---|
| 49 | # In this shortcut syntax, properties and their backing vars are |
|---|
| 50 | # declared in one line: |
|---|
| 51 | |
|---|
| 52 | class Person2 |
|---|
| 53 | |
|---|
| 54 | cue init(name as String) |
|---|
| 55 | base.init |
|---|
| 56 | _name = name |
|---|
| 57 | |
|---|
| 58 | pro name from var as String |
|---|
| 59 | |
|---|
| 60 | pro age from var as int |
|---|
| 61 | |
|---|
| 62 | |
|---|
| 63 | # You can even pack an initial value into the declaration |
|---|
| 64 | # which also be used to infer the data type. |
|---|
| 65 | |
|---|
| 66 | class Person3 |
|---|
| 67 | |
|---|
| 68 | pro name from var = '' # inferred as String |
|---|
| 69 | |
|---|
| 70 | pro age from var = 0 # inferred as int |
|---|
| 71 | |
|---|
| 72 | |
|---|
| 73 | # In this shortcut syntax, the vars were already declared so |
|---|
| 74 | # the property simply "... from var": |
|---|
| 75 | |
|---|
| 76 | class Person4 |
|---|
| 77 | |
|---|
| 78 | var _name as String |
|---|
| 79 | var _age as int |
|---|
| 80 | |
|---|
| 81 | cue init(name as String) |
|---|
| 82 | base.init |
|---|
| 83 | _name = name |
|---|
| 84 | |
|---|
| 85 | pro name from var |
|---|
| 86 | """ |
|---|
| 87 | The "from var" indicates that the type of the property, as well |
|---|
| 88 | as its value, is taken from the class variable with the matching |
|---|
| 89 | name (underscore + property name). When you later want to add |
|---|
| 90 | code for this property, just chop off the "from var" and write |
|---|
| 91 | the full property (pro foo as Type; get ...; set ...) |
|---|
| 92 | """ |
|---|
| 93 | |
|---|
| 94 | pro age from var |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | # If the underlying variable name is different than the property name, |
|---|
| 98 | # you can specify that name instead of "var": |
|---|
| 99 | |
|---|
| 100 | class Person5 |
|---|
| 101 | |
|---|
| 102 | var _name as String |
|---|
| 103 | |
|---|
| 104 | cue init(name as String) |
|---|
| 105 | base.init |
|---|
| 106 | _name = name |
|---|
| 107 | |
|---|
| 108 | pro nombre from _name |
|---|
| 109 | |
|---|
| 110 | |
|---|
| 111 | # Properties can be read-only: |
|---|
| 112 | |
|---|
| 113 | class Person6 |
|---|
| 114 | |
|---|
| 115 | cue init(name as String) |
|---|
| 116 | base.init |
|---|
| 117 | _name = name |
|---|
| 118 | |
|---|
| 119 | get name from var as String |
|---|
| 120 | |
|---|
| 121 | get lowerName as String |
|---|
| 122 | return _name.toLower |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | # Properties can be write-only: |
|---|
| 126 | |
|---|
| 127 | class Parts |
|---|
| 128 | |
|---|
| 129 | var _stuff = List<of Object>() |
|---|
| 130 | |
|---|
| 131 | set contents as List<of Object> |
|---|
| 132 | _stuff.clear |
|---|
| 133 | for item in value |
|---|
| 134 | _stuff.add(item) |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | # Properties can be protected, typically with an underscore, although |
|---|
| 138 | # it's not very common. Then only this class and subclasses can invoke |
|---|
| 139 | # them: |
|---|
| 140 | |
|---|
| 141 | class Foo |
|---|
| 142 | |
|---|
| 143 | get _mol as int # underscore implies `protected` |
|---|
| 144 | return 42 |
|---|
| 145 | |
|---|
| 146 | get goldenRatio as number is protected # `protected` can be explicit |
|---|
| 147 | return 1.618033989 |
|---|
| 148 | |
|---|
| 149 | def doSomething |
|---|
| 150 | # Note that when accessing underscored members, you no longer |
|---|
| 151 | # use the preceding ".": |
|---|
| 152 | assert _mol == 42 |
|---|
| 153 | |
|---|
| 154 | # Without an underscore, the "." is required: |
|---|
| 155 | assert .goldenRatio > 1.6 |
|---|