|
| 1 | +--- |
| 2 | +layout: recipe |
| 3 | +title: Class Variables and Instance Variables |
| 4 | +chapter: Classes and Objects |
| 5 | +--- |
| 6 | +## Problem |
| 7 | + |
| 8 | +You want to create class variables and instance variables (properties). |
| 9 | + |
| 10 | +## Solution |
| 11 | + |
| 12 | +### Class Variables |
| 13 | + |
| 14 | +{% highlight coffeescript %} |
| 15 | +class Zoo |
| 16 | + @MAX_ANIMALS: 50 |
| 17 | + MAX_ZOOKEEPERS: 3 |
| 18 | + |
| 19 | + helpfulInfo: => |
| 20 | + "Zoos may contain a maximum of #{@constructor.MAX_ANIMALS} animals and #{@MAX_ZOOKEEPERS} zoo keepers." |
| 21 | + |
| 22 | +Zoo.MAX_ANIMALS |
| 23 | +# => 50 |
| 24 | + |
| 25 | +Zoo.MAX_ZOOKEEPERS |
| 26 | +# => undefined (it is a prototype member) |
| 27 | + |
| 28 | +Zoo::MAX_ZOOKEEPERS |
| 29 | +# => 3 |
| 30 | + |
| 31 | +zoo = new Zoo |
| 32 | +zoo.MAX_ZOOKEEPERS |
| 33 | +# => 3 |
| 34 | +zoo.helpfulInfo() |
| 35 | +# => "Zoos may contain a maximum of 50 animals and 3 zoo keepers." |
| 36 | + |
| 37 | +zoo.MAX_ZOOKEEPERS = "smelly" |
| 38 | +zoo.MAX_ANIMALS = "seventeen" |
| 39 | +zoo.helpfulInfo() |
| 40 | +# => "Zoos may contain a maximum of 50 animals and smelly zoo keepers." |
| 41 | +{% endhighlight %} |
| 42 | + |
| 43 | + |
| 44 | +### Instance Variables |
| 45 | + |
| 46 | +You have to define instance variables (i.e. properties) inside a class' method, initialize your defaults in the constructor. |
| 47 | + |
| 48 | +{% highlight coffeescript %} |
| 49 | +class Zoo |
| 50 | + constructor: -> |
| 51 | + @animals = [] # Here the instance variable is defined |
| 52 | + |
| 53 | + addAnimal: (name) -> |
| 54 | + @animals.push name |
| 55 | + |
| 56 | + |
| 57 | +zoo = new Zoo() |
| 58 | +zoo.addAnimal 'elephant' |
| 59 | + |
| 60 | +otherZoo = new Zoo() |
| 61 | +otherZoo.addAnimal 'lion' |
| 62 | + |
| 63 | +zoo.animals |
| 64 | +# => ['elephant'] |
| 65 | + |
| 66 | +otherZoo.animals |
| 67 | +# => ['lion'] |
| 68 | +{% endhighlight %} |
| 69 | + |
| 70 | +#### WARNING! |
| 71 | +*Do not add the variable accidently to the prototype, by defining it outside the constructor* (Even if mentioned [elsewhere](http://arcturo.github.io/library/coffeescript/03_classes.html#content), this does not work as intended, due to the underlying JavaScript prototype concept). |
| 72 | + |
| 73 | +{% highlight coffeescript %} |
| 74 | +class BadZoo |
| 75 | + animals: [] # Translates to BadZoo.prototype.animals = []; and is thus shared between instances |
| 76 | + |
| 77 | + addAnimal: (name) -> |
| 78 | + @animals.push name # Works due to the prototype concept of Javascript |
| 79 | + |
| 80 | + |
| 81 | +zoo = new BadZoo() |
| 82 | +zoo.addAnimal 'elephant' |
| 83 | + |
| 84 | +otherZoo = new BadZoo() |
| 85 | +otherZoo.addAnimal 'lion' |
| 86 | + |
| 87 | +zoo.animals |
| 88 | +# => ['elephant','lion'] # Oops... |
| 89 | + |
| 90 | +otherZoo.animals |
| 91 | +# => ['elephant','lion'] # Oops... |
| 92 | + |
| 93 | +BadZoo::animals |
| 94 | +# => ['elephant','lion'] # The value is stored in the prototype |
| 95 | +{% endhighlight %} |
| 96 | + |
| 97 | +## Discussion |
| 98 | + |
| 99 | +Coffeescript will store the values of class variables on the class itself rather than on the prototype it defines. These are useful for defining variables on classes which can't be overwritten by instance attribute variables. |
0 commit comments