2011-05-10 10 views
10

CoffeeScriptを使用してクラスを拡張する方法はありますが、構築引数をsuperに渡す方法はありますか?クラスを拡張し、すべてのコンストラクタ引数をスーパーに渡します

例:

class List extends Array 
    # Some other stuff to make it work... 

list = new List(1,2,3) 

console.log list 
 
[1, 2, 3] 
+0

は、分離された二つにこの質問を分割するために素晴らしいと思いません。 superへのコンストラクタ引数の一般的な渡しの最初のもの、 'Array'の奇妙な振る舞いに関する第2のものです。 – Mitja

答えて

8
class List extends Array 
    constructor: -> 
     @push arguments... 

    toString: -> 
     @join('-') 

list = new List(1, 2) 

list.push(3) 

list.toString() 

=>

 
'1-2-3' 
+0

親オブジェクトのコンストラクタにすべての引数を渡す一般的な方法があるといいですが、これはこの場合の仕事です:) – Acorn

+1

Arrayは 'コンストラクタ'メソッドを持たないため、 、 それはいいだろう。 =) – jejacks0n

+0

この場合、「引数」が存在しないため、strictモードでは機能しません。 – monokrome

24

一般的に、これは追加コードなしで動作します。その配列はconstructor方法はありません

class A 
    constructor: -> 
    console.log arg for arg in arguments 

class B extends A 

new B('foo') # output: 'foo' 

、問題ではない:親のコンストラクタを明示的に上書きされない限り使用されている問題だけではArrayある

coffee> Array.constructor 
[Function: Function] 

は単なる奇妙です。配列は原則的に「単なるオブジェクト」ですが、実際には配列は別々に格納されます。したがって、コンストラクタを配列ではないオブジェクトに適用しようとすると(たとえそれがinstanceof Arrayテストに合格しても)、動作しません。

このように、Acornのソリューションを使用できますが、実際には、実際の配列が必要なものにListを渡した場合、他の問題が発生する可能性があります。そのため、ネイティブオブジェクト型からの継承を使用するのではなく、配列インスタンスのラッパーとしてListを実装することをお勧めします。

我々は、件名に1点の非常に重要な明確化いる間:あなたは、それ自体でsuperを使用し、は、すべての引数を渡すないこと!この動作はRubyから借用されています。 なし引数でコンストラクタ '

class B extends A 
    constructor: -> 
    super() 

Aを起動する一方、コンストラクタ' だから、

class B extends A 
    constructor: -> 
    super 

Aへのすべての引数に沿って渡します。

+0

すばらしい説明をありがとう! '' Listを配列インスタンスのラッパーとして実装することをお勧めします。 ''これをどうやってやりますか?あなたが時間を持っているなら、短い例が大いに評価されるでしょう! – Acorn

+0

さて、コンストラクタが '@arr = Array :: slice.call arguments、0'(argumentsメソッドをオブジェクトに変換する標準的なメソッド)のように見えるということは、配列メソッドのそれぞれを実装するということです単純なパススルーとして(例えば 'push: - > @ arr.push.apply arr、arguments'、' toString: - > @ arr.toString() '、...)、そして最後に独自の' List'メソッド。 –

+0

ああ、うわー、すべてのメソッドを個別に渡す。ちょっと面倒だね:) – Acorn

-1

JavaScriptの私の調査では、動的な数のコンストラクタ引数を持つクラスを作成するための一般的な方法が必要でした。前述のように、これは私が知っている限り配列に対しては機能しません。これは、コーヒースクリプトスタイルのクラスでのみ機能します。引数の動的数の特定の機能を呼び出す

.apply

args = [1, 2, 3] 
f = measurement.clone 

f.apply measurement, args 

を通してクラスが変数に保存されたクラスを拡張することができる十分に容易です。その結果、新しいサブクラスを返す関数を書くことができます。一緒にすべてを置く

classfactory = (f) -> 
    class extension extends f 

我々は、スーパークラスのコンストラクタにで我々apply引数の新しいサブクラスを返す関数を作成することができます。

classwitharguments = (f, args) -> 
    class extension extends f 
     constructor:() -> 
      extension.__super__.constructor.apply @, args 

この新工場

args = [1, 2, 3] 
instance = new (classwitharguments Measurement, args) 

思考を使用するには?コメント?提案?制限事項私は考えなかった?お知らせ下さい。

2

CoffeeScriptでextendsを使用すると、スーパークラスもCoffeeScriptになると予想されます。非CSクラスを使用している場合(例:元の質問にArrayが含まれていると、問題が発生する可能性があります。

これは私の一般的なケースを解決しました。おそらくコンパイルされたJSで使用されることを意図していない_superを使用しているので、ちょっとハックします。

class MyClass extends SomeJsLib 

    constructor: -> 
    _super.call @, arg1, arg2 

それとも、単に発信者からの引数パススルーする場合:

class MyClass extends SomeJsLib 

    constructor: -> 
    _super.apply @, arguments 
関連する問題