title: Dynamic class generation in CoffeeScript
body: <p>What is the best way to dynamically create classes in CoffeeScript, in order to later instantiate objects of them?</p>
  
  <p>I have found ways to do it, but I am not sure if there is maybe an even better (or simpler) way to achieve it. Please let me know your thoughts on my code.</p>
  
  <p>Let's start with simple non-dynamic classes:</p>
  
  <pre><code>class Animal
    constructor: (@name) -&gt;
  
    speak: -&gt;
      alert "#{@name} says #{@sound}"
  
  class Cat extends Animal
    constructor: (@name) -&gt;
      @sound = "meow!"
  
  garfield = new Cat "garfield"
  garfield.speak()
  </code></pre>
  
  <p>As expected, garfield says meow!</p>
  
  <p>But now we want to dynamically generate classes for more animals, which are defined as follows:</p>
  
  <pre><code>animalDefinitions = [
      kind:  'Mouse'
      sound: 'eek!'
    ,
      kind:  'Lion'
      sound: 'roar!'
    ]
  </code></pre>
  
  <p>The first naive attempt fails:</p>
  
  <pre><code>for animal in animalDefinitions
    animal.class = class extends Animal
      constructor: (@name) -&gt;
        @sound = animal.sound
  
  mutant = new animalDefinitions[0].class "mutant"
  mutant.speak()
  </code></pre>
  
  <p>The animal we just created, <code>mutant</code>, should be a mouse. However, it says roar! This is because animal.sound only gets evaluated when we instantiate the class. Luckily, from JavaScript we know a proven way to solve this: a closure:</p>
  
  <pre><code>for animal in animalDefinitions
    makeClass = (sound) -&gt;
      class extends Animal
        constructor: (@name) -&gt;
          @sound = sound
    animal.class = makeClass(animal.sound)
  
  mickey = new animalDefinitions[0].class "mickey"
  mickey.speak()
  
  simba = new animalDefinitions[1].class "simba"
  simba.speak()
  </code></pre>
  
  <p>Now it works as desired, mickey mouse says eek! and simba the lion says roar! But it looks somewhat complicated already. I am wondering if there is an easier way to achieve this result, maybe by accessing the prototype directly. Or am I completely on the wrong track?</p>