3

ミックスインを使って大きなクラスを分割したい。

リトルブックのこのミックスインコードを使用しています

@include: (obj) ->
    for key, value of obj when key not in moduleKeywords
      # Assign properties to the prototype
      @::[key] = value

    obj.included?.apply(@)
    this

class FooMixin

  b: => @something = 2

class Foo extends Module
  @include FooMixin

  a: => @something = 1

問題は、@であるということFooMixinですFooMixinFoo代わりになりたいです。

_.bind(@::[key], @)最後に行を追加しようとしました@include()が、役に立ちません。助言がありますか?

4

1 に答える 1

4

さて、私が間違っていたことはほとんどありません。

1.

@includefrom the Little Book は、クラスではなくオブジェクトを取ります。クラスで動作させるには、@include FooMixin::. しかし、それ以来、代わりにオブジェクトを使い始めました。

2.

クラスの代わりにオブジェクトを使用する場合、太い矢印は、CoffeeScript ラッパー内の一番上に行を追加します_this = this。すべてのメソッドは、私たちが望むものではないグローバル コンテキストにバインドされています。修正するには、太い矢印を細い矢印に変換し、各関数をFooインスタンスにバインドする必要があります。Underscore を使用して、これを のコンストラクターに追加しましたFoo

constructor: ->
  for fname in _.functions FooMixin
    @[fname] = _.bind @[fname], @
  super

試してみましたが、上記のコードがメソッドとほとんど同じであるため、奇妙なエラーの_.bindAll @, _.functions FooMixinようなエラーが表示されました。At Function.bind, could not run bind of undefined._.bindAll

これで、クラスを分割して読みやすくし、コードを共有できるようになりました。


更新: _.bindAll の問題は、配列ではなくスプラットを取ることです。を使用することを修正します_.bindAll @, _.functions(FooMixin)...

更新:より良い解決策が見つかりました。

元の投稿と同じ。ミックスインにクラスを使用します。

プロパティの代わりにプロトタイプを操作するために使用@include FooMixin::または変更します。@include

Fooコンストラクターで、メソッドを正しくバインドするように記述しFooMixin.call @ます。

これはうまく機能し、素晴らしくきれいです。

唯一の潜在的な問題は、ミックスインが既存のプロパティによってオーバーライドされることです。私が見ることができるこれを回避する唯一の方法は、次のようなことをすることです:

after = ->
  _.extend Foo, FooMixin::

class Foo
   # define...

after()

または、extend メソッドを に渡します_.deferが、これは非常にハックで、おそらく機能しません。

于 2012-10-11T14:10:03.387 に答える