Class Variables and Instance Variables
Problem
You want to create class variables and instance variables (properties).
Solution
Class Variables
class Zoo
@MAX_ANIMALS: 50
MAX_ZOOKEEPERS: 3
helpfulInfo: =>
"Zoos may contain a maximum of #{@constructor.MAX_ANIMALS} animals and #{@MAX_ZOOKEEPERS} zoo keepers."
Zoo.MAX_ANIMALS
# => 50
Zoo.MAX_ZOOKEEPERS
# => undefined (it is a prototype member)
Zoo::MAX_ZOOKEEPERS
# => 3
zoo = new Zoo
zoo.MAX_ZOOKEEPERS
# => 3
zoo.helpfulInfo()
# => "Zoos may contain a maximum of 50 animals and 3 zoo keepers."
zoo.MAX_ZOOKEEPERS = "smelly"
zoo.MAX_ANIMALS = "seventeen"
zoo.helpfulInfo()
# => "Zoos may contain a maximum of 50 animals and smelly zoo keepers."
Instance Variables
You have to define instance variables (i.e. properties) inside a class’ method, initialize your defaults in the constructor.
class Zoo
constructor: ->
@animals = [] # Here the instance variable is defined
addAnimal: (name) ->
@animals.push name
zoo = new Zoo()
zoo.addAnimal 'elephant'
otherZoo = new Zoo()
otherZoo.addAnimal 'lion'
zoo.animals
# => ['elephant']
otherZoo.animals
# => ['lion']
WARNING!
Do not add the variable accidently to the prototype, by defining it outside the constructor (Even if mentioned elsewhere, this does not work as intended, due to the underlying JavaScript prototype concept).
class BadZoo
animals: [] # Translates to BadZoo.prototype.animals = []; and is thus shared between instances
addAnimal: (name) ->
@animals.push name # Works due to the prototype concept of Javascript
zoo = new BadZoo()
zoo.addAnimal 'elephant'
otherZoo = new BadZoo()
otherZoo.addAnimal 'lion'
zoo.animals
# => ['elephant','lion'] # Oops...
otherZoo.animals
# => ['elephant','lion'] # Oops...
BadZoo::animals
# => ['elephant','lion'] # The value is stored in the prototype
Discussion
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.