Here are two different ways of defining a class in Coffeescript:
class Container
constructor: (@member) ->
secret = 3
dec = ->
if secret > 0
secret -= 1
true
else
false
service : ->
if dec() then @member else null
Container::stamp = (string) ->
@member + string
Container = (param) ->
@member = param
secret = 3
dec = ->
if secret > 0
secret -= 1
true
else
false
@service = ->
if dec() then @member else null
null
Container::stamp = (string) ->
@member + string
Both of these define a class called Container
with
- a public field
member
initialized by a constructor parameter - a private field
secret
- a private method
dec
- a privileged method
service
- a public method
stamp
We can use both in the same way:
myContainer = new Container 'abc'
console.log myContainer.member # abc
console.log myContainer.stamp 'def' # abcdef
console.log myContainer.service() # abc
console.log myContainer.service() # abc
console.log myContainer.service() # abc
console.log myContainer.service() # null
The version above on the left is the special class syntax that Coffeescript provides. However, to me, this extra layer of syntax seems to depart a bit from the "Coffeescript is just JavaScript" philosophy.
The version above on the right is a translation of Douglas Crockford's pattern, using his example.
Which is better? The left is a bit easier to read for a newcomer to the language, but I find the right more elegant because there is less "magic".
And there is another advantage to the Crockford style. Consider this small modification:
Container = (param, decrementBy) ->
@member = param
secret = 3
dec = ->
if secret > 0
secret -= decrementBy
true
else
false
@service = ->
if dec() then @member else null
null
Container::stamp = (string) ->
@member + string
Here we have generalized the class by adding a decrementBy
parameter to the constructor. We do not copy this to a property, but any of the private or privileged methods in the class can use it. (Don't you love closures!). There is no way to do this using the Coffeescript class
syntax in a way that would prevent the decrementBy value being modified from outside the object.
I think I might switch to using the Crockford-style classes.