[英]Dynamic class generation in CoffeeScript
在CoffeeScript中動態創建類的最佳方法是什么,以便稍后實例化它們的對象?
我已經找到了實現它的方法,但我不確定是否有更好(或更簡單)的方法來實現它。 請讓我知道您對我的代碼的看法。
讓我們從簡單的非動態類開始:
class Animal
constructor: (@name) ->
speak: ->
alert "#{@name} says #{@sound}"
class Cat extends Animal
constructor: (@name) ->
@sound = "meow!"
garfield = new Cat "garfield"
garfield.speak()
正如所料,加菲爾德說喵!
但現在我們想為更多動物動態生成類,其定義如下:
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()
我們剛創造的動物, mutant
,應該是一只老鼠。 然而,它說咆哮! 這是因為在我們實例化類時,只會對animal.sound進行求值。 幸運的是,從JavaScript我們知道一種可靠的方法來解決這個問題:一個閉包:
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! 和獅子說咆哮! 但它看起來有點復雜。 我想知道是否有更簡單的方法來實現這個結果,可能是直接訪問原型。 還是我完全走錯了路?
由於sound
是Animal實例的默認值,因此您可以將其設置為類定義的屬性:
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}"
對於你的直接問題(循環中的閉包不捕獲當前值,但是最新的閉包),有do
構造:
for animal in animalDefinitions
do (animal) ->
animal.class = class extends Animal
constructor: (@name) ->
@sound = animal.sound
不知何故,我預計的CoffeeScript自動照顧這一點,因為這是在JavaScript中一個常見的錯誤,但至少有do
有把它寫一個簡潔的方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.