Getters and setters are implemented using the Object.defineProperty method. We could implement each property with a call to this method, but I don't want to type a bunch of cruft to define each class property. So lets do it meta - after all, coffee-script IS javascript!
Function::get = ($def) -> $name = Object.keys($def)[0] Object.defineProperty @::, $name, {get: $def[$name], configurable: yes}Notice that I've augmented the Function object (:: is coffescript notation for prototype). This will add a get method to all functions, and in coffeescript a class is a function. We can define set the same way:
Function::set = ($def) -> $name = Object.keys($def)[0] Object.defineProperty @::, $name, {set: $def[$name], configurable: yes}But what does that get us? Lets look at an implementation:
class HeartOfGold _answer: 0 @get answer: -> @_answer @set answer: (value) -> @_answer = valueInside of a class definition, but outside of a method scope, @ (this) refers to the class. So we are calling the get method of the class that we defined earlier, to define a getter on the class.
And, if we explicitly invoke the super object, we can inherit the new attributes:
class Zaphod extends HeartOfGold # Explicit access to super is used to access property behavior @get answer: -> Zaphod.__super__.answer * 2 * Math.PI @set answer: (value) -> Zaphod.__super__.answer = value constructor: (value) -> @answer = value meaning_of_life = new Zaphod(6.684507609859605) console.log "Zaphod says that the meaning of life, the universe, and everything is "+meaning_of_life.answerRun like this -
$ coffee heartofgold Zaphod says that the meaning of life, the universe, and everything is 42Now aren't we glad we didn't turn into a big ball of yarn!
(updated: to use google prettify rather than embedded gists. It makes it easier to focus on the code)
No comments:
Post a Comment