在CoffeeScript中生成动态类 [英] Dynamic class generation in CoffeeScript

查看:124
本文介绍了在CoffeeScript中生成动态类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在CoffeeScript中动态创建类的最佳方法是什么,以便以后实例化它们的对象?

What is the best way to dynamically create classes in CoffeeScript, in order to later instantiate objects of them?

我已经找到了办法,但我不知道是否可能有一个更好(或更简单)的方式来实现它。请让我知道您对我的代码的想法。

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.

让我们从简单的非动态类开始:

Let's start with simple non-dynamic classes:

class Animal
  constructor: (@name) ->

  speak: ->
    alert "#{@name} says #{@sound}"

class Cat extends Animal
  constructor: (@name) ->
    @sound = "meow!"

garfield = new Cat "garfield"
garfield.speak()

正如预期,加菲猫说喵!

As expected, garfield says meow!

但现在我们想动态生成更多动物的类,定义如下:

But now we want to dynamically generate classes for more animals, which are defined as follows:

animalDefinitions = [
    kind:  'Mouse'
    sound: 'eek!'
  ,
    kind:  'Lion'
    sound: 'roar!'
  ]

尝试失败:

for animal in animalDefinitions
  animal.class = class extends Animal
    constructor: (@name) ->
      @sound = animal.sound

mutant = new animalDefinitions[0].class "mutant"
mutant.speak()

我们刚刚创建的动物突变应该是鼠标。然而,它说吼!这是因为animal.sound只有在我们实例化类时才被评估。幸运的是,从JavaScript我们知道一个可行的解决方法:一个闭包:

The animal we just created, mutant, 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:

for animal in animalDefinitions
  makeClass = (sound) ->
    class extends Animal
      constructor: (@name) ->
        @sound = sound
  animal.class = makeClass(animal.sound)

mickey = new animalDefinitions[0].class "mickey"
mickey.speak()

simba = new animalDefinitions[1].class "simba"
simba.speak()

现在它可以按照需要工作,米老鼠说eek!和simba狮子说吼!但它看起来有点复杂了。我想知道是否有一个更简单的方法来实现这个结果,也许通过直接访问原型。

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?

推荐答案

由于声音一个Animal实例的默认值,可以将其设置为类定义上的一个属性:

Since sound is a default value for an Animal instance, you can set it as a property on class definition:

class Cat extends Animal
    sound: 'meow!'

garfield = new Cat "garfield"
garfield.speak() # "garfield says meow!"

然后

for animal in animalDefinitions
    animal.class = class extends Animal
        sound: animal.sound

mutant = new animalDefinitions[0].class "mutant"
mutant.speak() # "mutant says eek!"

如果您希望 sound 你可以做

class Animal
    constructor: (@name, sound) ->
        @sound = sound if sound? 
    speak: ->
        console.log "#{@name} says #{@sound}"

这篇关于在CoffeeScript中生成动态类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆