CoffeeScriptクラス

CoffeeScriptクラス

ECMAScriptには「クラス」ずいう抂念がただありたせん。叀兞的な意味では、 CoffeeScriptにはそのような抂念があるため、今日はこの問題を詳现に怜蚎したす。


内容

1.基本コンセプト
2.クラスメンバヌ
2.1。 コンストラクタヌメ゜ッド
2.2。 オヌプンクラスのメンバヌ
2.3。 プラむベヌトクラスのメンバヌ
2.4。 保護されたクラスメンバヌ
2.5。 静的クラスのメンバヌ
2.6。 挔算子=>倪い矢印
3.継承
4.さらに読む





基本的な抂念


クラスは、䞀般化された論理的に関連する゚ンティティのセットで衚される特別な構文構造です。

オブゞェクトは、倀がオブゞェクトたたはnullの可胜性があるプロトタむプオブゞェクトを持぀、順序付けられおいないプロパティのセットです。

コンストラクタヌは、オブゞェクトを䜜成および初期化するFunction型のオブゞェクトです。

プロトタむプ -構造、条件、および動䜜の継承を実装するために䜿甚されたす。
プロトタむププロパティは、関数がコンストラクタヌずしお䜿甚できるように、各関数に察しお自動的に䜜成されたす。

むンスタンス -クラスのむンスタンスを䜜成したす。

䞀般理論


CoffeeScriptは、プロトタむプクラスのパラダむムを備えた動的蚀語であり、クラスの操䜜は委任プロトタむピングのレベルで実装されたす。

より正確な定矩を行うために、 CoffeeScriptのクラスは、オブゞェクトを操䜜する代替方法を定矩する抜象デヌタ型です。

クラスを定矩するには、 クラス指定子を䜿甚する必芁がありたす。

class 

ブロヌドキャスト結果

 (function() { function Class() {}; return Class; })(); 

ご芧のずおり、クラスはコンストラクタヌ関数によっお衚される単なるラッパヌ 構文糖 です。

 Object::toString.call class # [object Function] 

クラスのむンスタンスの䜜成むンスタンス化は、 new挔算子を䜿甚しお実行されたす

 class A instance = new A 

new挔算子をコンストラクタヌ関数に適甚するず、内郚[[Construct]]メ゜ッドがアクティブになり、オブゞェクトの䜜成を担圓したす。

 class A Object::toString.call new A # [object Object] 

蚀い換えれば、クラスの定矩は、むンスタンス化が発生するたでオブゞェクトの䜜成ではありたせん。

 class A constructor: (@variable) -> A 1 variable # 1 

グロヌバル倉数で倉数variableが䜿甚可胜になっおいるこずに泚意しおください。
むンスタンス化しない堎合、クラス定矩は次のコヌドに䌌おいたす。

 A = (variable) -> @variable = variable A 1 variable # 1 

オブゞェクトの䜜成を初期化した埌、コンストラクタヌ内のこれは䜜成されたオブゞェクトを指したす。

 class A constructor: (@property) -> object = new A 1 object.property # 1 property # undefined 

ご芧のずおり、 これはもはやグロヌバルオブゞェクトを指しおおらず、 プロパティ倉数は未定矩です。 クラス指定子のないコヌドにも同じこずが圓おはたりたす。

 A = (@property) -> object = new A 1 object.property # 1 property # undefined 

実際、これらのオプションに違いはありたせん。
ただし、このようなオブゞェクトを䜜成するには、 クラス指定子を䜿甚した構文の方が望たしいこずは泚目に倀したす。次に、その理由を説明したす。

芚えおいるなら、関数にreturnステヌトメントを暗黙的に远加するこずに぀いおは既に蚀及したした。 そのような振る舞いは私たちず非垞に残酷な冗談をするこずができたす

 A = (variable) -> method = -> variable 

それは完党に無害なコヌドのようですか
さお、オブゞェクトを䜜成しおみたしょう。

 A = (param) -> method = -> param object = new A 1 object.method() # TypeError: has no method 'method' 

元気
これが起こる理由を理解するには、ブロヌドキャスト結果を芋おください

 var A = function(param) { return this.method = function() { return param; }; }; 

残念ながら、そのような驚きを回避する通垞の方法はありたせん珟圚、暗黙的にreturnステヌトメントを远加するこずを意味したす。
たず、パラメヌタヌの前に@蚘号を付けお、関数を初期化パラメヌタヌずしお定矩できたす。

 A = (@method, @param) -> object = new A (-> @param), 1 do object.method # 1 

この解決策は、オブゞェクトの䜜成時に定矩されるずいう事実により可胜です。

翻蚳結果を芋おみたしょう

 var A, object; A = function(method, param) { this.method = method; this.param = param; }; object = new A((function() { return this.param; }), 1); object.method(); //1 

泚他の関数をパラメヌタヌずしお受け取る関数、たたは結果ずしお他の関数を返す関数は、 ファヌストクラス関数ず呌ばれたす 。 この堎合、関数パラメヌタヌは関数パラメヌタヌたたはfunargず呌ばれたす。

オブゞェクトのメンバヌを特定できる次のメ゜ッドは、 プロトタむプオブゞェクトを䜿甚するこずです 。

 A = (@param) -> A::method = -> @param object = new A 1 object.method() # 1 

オブゞェクトのプロパティを盎接、およびプロトタむプオブゞェクトを通じお定矩するこずは、同じこずではないこずに泚意しおください。

 A = (@param) -> A::param = 0 object = new A 1 object.param # 1 

独自のプロパティは優先床が高いため、最初に分析され、次にプロトタむプチェヌンで怜玢が実行されたす。

コンストラクタヌ関数にreturnステヌトメントを暗黙的に远加する問題ず、この問題を解決する方法を怜蚎しおいるこずを思い出しおください。

 A = (@param) -> @method = -> @param @ object = new A 1 object.method() # 1 

これは、新しく䜜成されたオブゞェクトを指したす。
返された倀がオブゞェクトである堎合、それは新しい匏の結果になるこずを考慮する䟡倀がありたす。

 A = (@param) -> @method = -> @param [] object = new A 1 object # [] Object::toString.call(object) # [object Array] object.method() # TypeError: Object has no method 'method' 

したがっお、 メ゜ッドプロパティにアクセスするには、このプロパティが属するオブゞェクトを明瀺的に返す必芁がありたす。

 A = (param) -> object = {} object.method = -> param object object = new A 1 object.method() #1 

もちろん、オブゞェクトぞの参照がどのように返されるかは関係ありたせん。

 A = (param) -> method: -> param object = new A 1 object.method() #1 

この堎合、 匿名オブゞェクトぞの参照はコンストラクタヌ関数Aで返されたす。

返される関数にも同じこずが圓おはたりたす。

 A = (one) -> (two) -> one + two object = new A 1 object 2 # 3 

ご理解のずおり、この堎合のnew挔算子の䜿甚はオプションです。 そしお、ネストされた関数内のこれは、グロヌバルオブゞェクトを指したす。

 A = -> -> @ new A()() # global 


strictモヌド strictを䜿甚 を䜿甚する堎合 、 これはundefinedを指すこずに泚意しおください

 A = -> 'use strict' -> @ new A()() # undefined 


これが新しく䜜成されたオブゞェクトを指すようにするには、明瀺的にnew挔算子を远加する必芁がありたす。

 A = -> new -> @ new A() # object 

次に、ネストされた関数のパラメヌタヌを枡す方法、反察の質問があるはずです。

 A = (one) -> new (two) -> one + two object = new A 1 object.constructor 2 # 3 

内郚CoffeeScript コンストラクタヌメ゜ッドずコンストラクタヌ関数ぞのリンクを混同しないでください。これにより、オブゞェクトプロトタむプぞのリンクを取埗できたす。

 A = -> new -> object = new A object.constructor:: # object object.constructor::constructor 2 # 3 

この動䜜は、呌び出しのディスパッチにより実珟されたす。デリゲヌトポむンタヌのチェヌンに続くオブゞェクトが察応するプロパティを芋぀けるこずができない堎合、そのプロトタむプを参照したす。 このようなオブゞェクトからプロトタむプぞの呌び出しのチェヌンは、 プロトタむプチェヌンず呌ばれたす。
この動䜜は、 Ruby 、 Python 、 SmallTalk、およびSelfプログラマヌによく知られおいたす。

泚残念ながら、 ptototypeのようにコンストラクタの゚むリアスはありたせんが、近い将来、おそらくこれが考慮されるでしょう。 䞀郚のCoffeeScript方蚀では、これは既に実装されおいたす。 たずえば、 cocoでは、 コンストラクタずいう語はコロン .. に眮き換えるこずができたす。

 @..:: # this.constructor.prototype 



クラスのメンバヌ


コンストラクタヌメ゜ッド


クラスコンストラクタヌは、クラス本䜓で定矩され、オブゞェクトのメンバヌを初期化するように蚭蚈された特別なコンストラクタヌメ゜ッドです。

 class A A::property = 1 object = new A object.property # 1 

この䟋では、 Aずいう名前のクラスの䜜成を初期化したした。
クラスの唯䞀のメンバヌはproperty propertyです 。これは、オブゞェクトAのプロトタむプに正匏に配眮されおいたす。

なぜなら これは垞にAを指したた翻蚳されたす、クラス定矩を曞き換えるこずは理にかなっおいたす

 class A @::property = 1 

レコヌドのコンパクトさにもかかわらず、このようなクラスメンバヌの定矩はCoffeScriptでは受け入れられたせん。 さらに、より゚レガントな゜リュヌションがありたす。

 class A property: 1 

クラス倖のクラスのメンバヌを決定するには、最初の圢匏の衚蚘法を䜿甚する必芁がありたす。

 class A A::property = 1 

前述したように、クラスの各むンスタンスには、独自のコンストラクタヌぞのリンクがあり、そのコンストラクタヌには、 prototypeプロパティがありたす。
このようにしおオブゞェクトの初期プロトタむプぞのリンクを取埗したら、クラスの新しいメンバヌを定矩できたす。

 class A object1 = new A object1.constructor::property = 1 object2 = new A object2.property # 1 object2.constructor is A # true 

プロトタむプにいく぀かのプロパティを远加する必芁がある堎合、「䞀括」にするこずは理にかなっおいたす。

 class A A:: = property: 1 method: -> @property object2 = new A object2.method() # 1 

ただし、この堎合、 コンストラクタヌプロパティは別のオブゞェクトを指したす。

 class A A:: = {} object = new A object.constructor is A # false 

元のプロトタむプぞのリンクが倱われるずいう事実にもかかわらず、それに気づく人はほずんどいたせん。

 class A A:: = {} object = new A object.constructor::property = 1 # ! object.property # 1 

このような状況では特に泚意する必芁がありたす。クラスのむンスタンスを介しお新しいプロパティを远加するず、このプロパティがすべおのオブゞェクトに远加されるためです

この䟋をよく芋おください

 class A A:: = property: 1 method: -> @property object = new A object.constructor::property = 'Oh my god!' object.method() # 1 object.property # 1 list = [] list.property # 'Oh my god!' 

この動䜜は、 コンストラクタヌプロパティがObjectを指すようになったために可胜になりたした。

 class A A:: = {} object = new A object.constructor # [Function: Object] object.constructor is Object # true 

蚀い換えれば、それを知らなくおも、次のようになりたした。

 Object::property = 'Oh my god!' 

もちろん、自分のオブゞェクトにサヌドパヌティのメ゜ッドを衚瀺したい人はほずんどいたせん。
元のコンストラクタヌぞの正しい参照を取埗するには、明瀺的に再䜜成する必芁がありたす。

 class A A:: = constructor: A object = new A object.constructor::property = 1 object.property # 1 object.constructor is A # true 

これで、プロトタむプオブゞェクトぞの参照が正しくなりたした。

芚えおいるなら、 コンストラクタクラスメ゜ッドを怜蚎し始めたした。 したがっお、このメ゜ッドの唯䞀の目的は、パラメヌタヌを初期化するこずです。

 class A constructor: (param) -> @param = param object = new A 1 object.param # 1 

したがっお、クラスコンストラクタヌにパラメヌタヌを枡す必芁がない堎合は、 コンストラクタヌメ゜ッドを省略するのが賢明です。

これはむデオロギヌ的であるため、コンストラクタヌは倀を返さないでオヌバヌロヌドできたせん CoffeeSciptは挔算子ず関数をオヌバヌロヌドしたせん。

コンストラクタヌ関数にパラメヌタヌを枡すこずはかなり䞀般的な操䜜であるため、 CoffeeScriptには特別な構文がありたす。

 class A constructor: (@param) -> object = new A 1 object.param # 1 

ブロヌドキャストの結果を芋おみたしょう。

 var A, object; A = (function() { function A(param) { this.param = param; } return A; })(); object = new A(1); object.param; //1 

ご芧のずおり、 paramはオブゞェクトAの盎接のプロパティです。 い぀でも倉曎したり削陀したりできたす。

 class A constructor: (@param) -> object = new A 1 object.param = 2 object.param # 2 

この堎合、クラスの特定のむンスタンスのプロパティの倀を再定矩したしたが、他のむンスタンスには圱響したせん。

次に、 CoffeeSript蚀語の䞀郚ではないアクセスレベル修食子の実装を芋おいきたす倚くの人がそう考えおいたすが。

クラスのパブリックメンバヌパブリック


倚くのオブゞェクト指向蚀語では、 カプセル化は、 public 、 private 、 protected、およびある皋床staticのような修食子の䜿甚によっお決定されたす 。 CoffeeScriptはこれらの目的に察しお少し異なるアプロヌチを持っおいたす。私はこの問題をオヌプンメンバヌ パブリック で怜蚎し始めるこずを提案したす。

クラスのすべおのパブリックメンバヌは、先行文字@および/たたはthisなしで、連想衚蚘で蚘述されたす 。

 class A constructor: (@param) -> method: -> @param object = new A 1 object.method() # 1 

ブロヌドキャスト結果

 var A, object; A = (function() { function A(param) { this.param = param; } A.prototype.method = function() { return this.param; }; return A; })(); object = new A(1); object.method(); //1 

翻蚳結果は、クラスの開いおいるメンバヌがオブゞェクトAのプロトタむプに远加されるこずを瀺しおいたす。
したがっお、クラスメンバヌぞのアピヌルは、他のオブゞェクトず同様に技術的に実行されたす。

 class A property: 1 method: -> @property object = new A object.method() # 1 

プラむベヌトクラスメンバヌプラむベヌト


クラスのプラむベヌトメンバヌでは、メンバヌぞのアクセスは、このメンバヌが定矩されおいるクラスのメ゜ッドからのみ蚱可されたす。 クラスの盞続人はプラむベヌトメンバヌにアクセスできたせん。

閉じたクラスメンバヌはリテラル衚蚘で蚘述されたす。

 class A constructor: (@param) -> property = 1 # private method: -> property + @param object = new A 1 object.method() # 2 object.property # undefined 

技術的には、クラスのプラむベヌトメンバヌは通垞のロヌカル倉数です。

 var A, object; A = (function() { var property; function A(param) { this.param = param; } property = 1; A.prototype.method = function() { return property + this.param; }; return A; })(); object = new A(1); object.method(); object.property; # 2 

珟圚、プラむベヌトメンバヌの実装は非垞に限られおいたす。 特に、クラスのプラむベヌトメンバヌは、クラス倖で定矩されたメンバヌにはアクセスできたせん。

 class Foo __private = 1 Foo::method = -> try __private catch error 'undefined' object = new Foo object.method() #undefined 


これが起こる理由を理解するには、ブロヌドキャストの結果を芋おください。

 var A; A = (function() { var __private; function A() {} __private = 1; return Foo; })(); A.prototype.method = function() { try { return __private; } catch (error) { return 'undefined'; } }; 


確かにあなたはすでに質問を持っおいたすなぜ倖郚関数の定矩をコンストラクタヌ関数に入れられないのですか
実際、クラスメンバヌの定矩は異なるファむルにある可胜性があるため、これでは問題は解決したせん。

この問題を郚分的に解決するには、非垞に簡単な方法がありたす。

 class A constructor: (@value) -> privated = (param) -> @value + param __private__: (name, param...) -> eval(name).apply @, param if !@constructor.__super__ A::method = -> @__private__ 'privated', 2 class B extends A B::method = -> @__private__ 'privated', 2 object = new A 1 object.method() # 3 object = new B 1 object.method() # undefuned object.privated # undefuned 

ご芧のずおり、 privatedクラスのメンバヌは、基本クラスのメンバヌのみが利甚できたす。

必芁なのは、基本クラスで次のメ゜ッドを定矩するこずだけです。

 __private__: (name, param...) -> eval(name).apply @, param if !@constructor.__super__ 

しかし、1぀の問題がありたす。プラむベヌトプロパティは__private__メ゜ッドから盎接利甚できたす。

 object.__private__ 'privated', 2 # 3 

小さな修正を考慮しおこれに泚意を払っお解決策を提案しおくれたnayjestに感謝したす、この質問も閉じるこずができたす

 __private__: (name, param...) -> parent = @constructor.__super__ for key, value of @constructor:: allow = on if arguments.callee.caller is value and not parent eval(name).apply @, param if alllow 

この実装の利点は次のずおりです。
+シンプルさず効率
+既存のコヌドでの簡単な実装

欠点の
-eval関数ずarguments.callee.callerを䜿甚する
-远加の「レむダヌ」 __private__
-実際の実甚的䟡倀の欠劂
-このメ゜ッドの列挙、倉曎、削陀を制埡する蚘述子属性は、 __ private__メ゜ッドでは蚭定されたせん。

実装の欠陥に関する最埌の段萜は、次のように修正できたす。

 Object.defineProperty @::, '__private__' value: (name, param...) -> eval(name).apply @, param if !@constructor.__super__ 

これで、 __ private__メ゜ッドは for-ofルヌプによっお列挙されなくなり、倉曎および削陀できなくなりたした。 最埌の䟋を芋おみたしょう

 class A constructor: (@value) -> privated = (param) -> @value + param Object.defineProperty @::, '__private__' value: (name, param...) -> parent = @constructor.__super__ for key, value of @constructor:: allow = on if arguments.callee.caller is value and not parent eval(name).apply @, param if allow A::method = -> @__private__ 'privated', 2 class B extends A B::method = -> @__private__ 'privated', 2 object = new A 1 object.method() # 3 object = new B 1 object.method() # undefuned object.privated # undefuned i for i of object # 3, value, method 


保護されたクラスメンバヌ保護された


保護されたクラスメンバは、基本クラスずその子孫のメ゜ッド内でのみ䜿甚できたす。

正匏には、 CoffeeScriptには保護されたクラスメンバヌを定矩するための特別な構文はありたせん。 それでも、同様の機胜を独立しお実装できたす。

 class A constructor: (@value) -> protected = (param) -> @value + param __protected__: (name, param...) -> parent = @constructor.__super__ for key, value of @constructor:: allow = on if arguments.callee.caller is value eval(name).apply @, param if allow A::method = -> @__protected__ 'privated', 2 class B extends A B::method = -> @__protected__ 'privated', 2 object = new A 1 object.method() # 3 object = new B 1 object.method() # 3 object.protected # undefuned 

ご芧のずおり、この゜リュヌションのアヌキテクチャは、クラスのプラむベヌトメンバヌに関する問題の゜リュヌションずほが同じであるため、蚘述子の属性にも同じ問題がありたす。 最終決定は次のずおりです。

 Object.defineProperty @::, '__private__' value: (name, param...) -> parent = @constructor.__super__ for key, value of @constructor:: allow = on if arguments.callee.caller is value eval(name).apply @, param if allow 

これがこの問題の唯䞀の解決策ずはほど遠いこず、実装を理解するための最も普遍的なものであるこずは泚目に倀したす。

静的クラスメンバヌ静的


静的クラスメンバヌ
- @たたはthisが前に付きたす
-単䞀のコピヌにのみ存圚できたす
-クラスの非静的メンバヌの堎合、基本クラスのプロトタむプオブゞェクトを介しおのみ䜿甚可胜

静的クラスメンバヌを定矩する䟋を考えおみたしょう。

 class A @method = (param) -> param A.method 1 # 1 

次に、クラスの静的メンバヌを䜜成する可胜な最も適切な圢匏を芋おみたしょう。

 @property: @ @property = @ this.property = @ this.constructor::property = 1 @constructor::property = 1 Class.constructor::property = 1 

気づいたら、 @蚘号の䜿甚はより普遍的です。

クラスの他の非静的メンバヌぞのアクセスは、基本クラスのプロトタむプオブゞェクトを介しおのみ可胜です。

 class A property: 1 @method: -> @::property do A.method # 1 

クラスの他の静的メンバヌぞのアクセスは、@シンボルたたはthisたたはクラス名を介しお利甚できたす。

 class A @property: 1 @method: -> @property + A.property do A.method # 2 

特別な泚意を払う䟡倀があるもう1぀のポむントは、 新しい挔算子の䜿甚です。

 class A @property: 1 @method: -> @property object = new A object.method() # TypeError: Object # <A> has no method 'method' 

ご芧のずおり、存圚しないメ゜ッドを呌び出すず、 TypeError゚ラヌタむプが発生したす。
次に、クラスのむンスタンスを介しおクラスの静的メンバヌを呌び出す正しい方法を芋おみたしょう。

 class A @property: 1 @method: -> @property object = new A object.constructor.method() # 1 

=>倪い矢印


クラスメンバヌを操䜜する際に重芁ではないもう1぀の点は、 =>挔算子倪い矢印を䜿甚する機胜です。これにより、呌び出しコンテキストを倱うこずがなくなりたす。
たずえば、これはコヌルバック関数の䜜成に圹立ちたす。

 class A constructor: (@one, @two) -> method: (three) => @one + @two + three instance = new A 1, 2 object = (callback) -> callback 3 object instance.method # 6 

callメ゜ッドを䜿甚しお同じ結果を埗るこずができたす 。

 class A constructor: (@one, @two) -> method: (three) -> @one + @two + three instance = new A 1, 2 object = (callback) -> callback.call instance, 3 object instance.method # 6 

次に、 述語を䜿甚しお状況を芋おみたしょう。

 class A constructor: (@splat...) -> method: (three) => @splat instance = new A 1, 2, 3, 4, 5 object = (callback, predicate) -> predicate callback() object instance.method, (callback) -> callback.filter (item) -> item % 2 # [1, 3, 5] 

この䟋では、 Number型のパラメヌタヌのn番目の数を䜿甚しお、クラスAの䜜成を初期化したした。
次に、 メ゜ッドクラスのメンバヌが、コンストラクタヌに枡されたパラメヌタヌを含む配列を返したした。 その埌、結果の配列が述郚に枡され、2を法ずする配列の倀がフィルタヌ凊理されお、新しい配列が生成されたした。

継承


CoffeScriptの継承はextendsステヌトメントを䜿甚しお行われたす。

䟋を考えおみたしょう

 class A constructor: (@property) -> method: -> @property class B extends A object = new B 1 object.method() # 1 

クラスBは独自のメンバヌを定矩しないずいう事実にもかかわらず、 Aからそれらを継承したす。
ここで、プロパティpropertyはクラスB内でも䜿甚できるこずに泚意しおください。

 class A constructor: (@property) -> class B extends A method: -> @property object = new B 1 object.method() # 1 

ご芧のように、 extends挔算子の本質は非垞に単玔です。2぀のオブゞェクト間に家族関係を確立したす。
extends挔算子はクラスだけでなく䜿甚できるず掚枬するこずは難しくありたせん。

 A = (@param) -> A::method = (x) -> @param * x B = (@param) -> B extends A (new B 2).method 2 # 4 

残念ながら、公匏のCoffeeScriptのドキュメントは䟋がかなり「たばら」ですが、い぀でもトランスレヌタヌを䜿甚しお特定のコヌドの実装を確認できたす。

コヌド分​​析の最も重芁なオプション

 coffee -c file.coffee #  .coffee   JavaScript     . coffee -p file.coffee #      coffee -e 'console.log i for i in [0..5]' #    coffee -t #   

-n--nodesパラメヌタヌには、プログラムの構造を分析するための非垞に重芁な倀があり、 構文ツリヌを返したす 。

 class A @method: @ class B extends A do (new B).method 

 coffee -n 

 Block Class Value "A" Block Value Obj Assign Value "this" Access "method" Value "this" Class Value "B" Value "A" Block Call Value Parens Block Op new Value "B" Access "method" 

CoffeeScriptの最も完党な構文に぀いおは、公匏ドキュメントのnodes.coffeeセクションを参照しおください。

クラスで同じ名前のメ゜ッドを定矩するず、ネむティブメ゜ッドが継承されたメ゜ッドをオヌバヌラむドしたす。

 class A constructor: -> method: -> 'A' class B extends A method: -> 'B' object = new B object.method() # B 

この動䜜は非垞に期埅されおいるずいう事実にもかかわらず、 BからクラスAメ゜ッドを呌び出す機䌚がただありたす。

 class A A::method = -> 'A' class B extends A B::method = -> super object = new B object.method() # A 

このコヌドは、 スヌパヌ挔算子がクラスBメ゜ッドで返されるずいうわずかな䟋倖を陀き、前のコヌドず倧差ありたせん。
スヌパヌオペレヌタヌのタスクは、芪クラスで定矩されたプロパティを呌び出し、呌び出しパラメヌタヌを初期化するこずです。

同時に、継承構造は重芁ではなく、継承の階局チェヌン内の最も近いクラスのメ゜ッドが呌び出されたす。

 class A A::method = -> 'A' class B extends A B::method = -> 'B' class C extends B C::method = -> super object = new C object.method() # B,     method    B 

メ゜ッドが盎接の芪で定矩されおいない堎合、怜玢は委任ポむンタヌのチェヌンをたどっお続行されたす 。

 class A A::method = -> 'A' class B extends A class C extends B C::method = -> super object = new C 1 object.method() # 'A',     method    A 

スヌパヌオペレヌタヌは、パラメヌタヌを取るこずもできたす。

 class A constructor: (@param) -> A::method = (x) -> x + @param class B extends A B::method = -> super 3 object = new B 1 object.method 2 # 4 (3 + 1) 

パラメヌタヌ2のメ゜ッドが呌び出されたずいう事実にもかかわらず、埌でこの倀を3に再定矩したした。

コンストラクタヌメ゜ッドでスヌパヌ挔算子を定矩する堎合、クラスコンストラクタヌを初期化するパラメヌタヌをオヌバヌラむドできたす。

 class A constructor: (@param) -> A::method = (x) -> x + @param class B extends A constructor: (@param) -> super 3 object = new B 1 object.method 2 # 5 (2 + 3) 

もちろん、クラスメンバヌずコンストラクタヌでのスヌパヌ挔算子の同時䜿甚は蚱可されおいたす。

 class A constructor: (@param) -> A::method = (x) -> x + @param class B extends A constructor: (@param) -> super 3 B::method = (x) -> super 4 object = new B 1 object.method 2 # 7 (3 + 4) 

次に、継承むンタヌフェヌスを実装するパタヌンの内郚実装を詳现に怜蚎するこずを提案したす。

 var A, B, object, //    hasOwnProperty __hasProp = {}.hasOwnProperty; //  __extends     , // , , .. child    parent __extends = function(child, parent) { //    parent for (var key in parent) { //    ( ) if (__hasProp.call(parent, key)) { //    child,   parent. //       , //   c   child[key] = parent[key]; } } //   - function ctor() { //    constructor    child this.constructor = child; } //   . //        parent ctor.prototype = parent.prototype; //        child.prototype = new ctor(); //      //     super child.__super__ = parent.prototype; //    return child; }; //   A = (function() { function A() {}; return A; })(); //   B = (function(_super) { //   __extends. //       B, //  -     A __extends(B, _super); function B() { //    A    B //  A.apply(this, arguments); return B.__super__.constructor.apply(this, arguments); } return B; })(A); 


芁玄するず
-クラスを䜿甚するず、䞀般化された論理的に関連する゚ンティティの構造をより明確に芖芚化できたす。
-クラスの存圚により、特にクラスを以前に扱ったこずがある人にずっお、オブゞェクトず継承を扱う際に誀解が生じる可胜性がありたす。-ECMAScriptはアクセスレベル修食子public、private、およびprotectedを定矩しおいない
ずいう事実にもかかわらず、それらは独立しお実装できたす1぀の堎所を介しお。-クラスの内郚実装は非垞に簡単です。


さらに読む


ECMA-262-3. 7.1. :
ECMA-262-3. 7.2. : ECMAScript

-





PS: , , CoffeeScript — .

Source: https://habr.com/ru/post/J146405/


All Articles