ダミーのJavascript継承

javascriptに関する別のスマートブックを読んだ後、継承を実装する方法を理解し始めました。 まあ、それはもちろん、実際の大規模なプロジェクトでは、いくつかのライブラリの関数を使用するのが最善であることは誰にとっても明らかです(それらの多くがあります)が、実際にそれが一般的にどのように機能するかを本当に理解したいです。



このテーマの内容を確認することにしました-一般的に、これを行わない方が良いでしょう-誰かが松葉杖についての記事をいくつかのページで書いています。シリアル番号。 一般に、多くの楽しみ、多くのコード、紛争も十分ですが、ベース自体は存在しません。 そして、私はそれを修正するのがいいだろうと思った。





1.それで、問題は正確に何ですか?



問題は、javascriptになじみのある継承がないことです。 できる最大のことは、クラスコンストラクターを作成することです。



function Class(){/*   *}
      
      





そして、プロトタイプを通して、すべてのインスタンスで同じになるメソッド、定数、および静的変数を追加します。



 Class.prototype = {/**/}
      
      





ほとんどの場合これで十分ですが、場合によってはそれ以上が必要です。



2.そして、本当にしたい場合は...



...その後、実装できます。 古典的な方法は次のようになります。



 function inherit_A(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.super = Parent.prototype; }
      
      





そして、あなたはそれを使うことさえできます:



 $(document).ready(function () { function Man(name) { this.name = name } Man.prototype.say = function () { console.log("My name is " + this.name) } function Gentleman(name) { Man.call(this, name); } inherit_A(Gentleman, Man); });
      
      





確かに、彼には小さな問題が1つあります。通常、プロトタイプを作成するために、上記のようにオブジェクト表記を使用します。



 Class.prototype = { /**/ }
      
      





そして、この継承では、このメソッドを実際には使用しません。私の関数が継承したプロトタイプを完全に消去するか、継承したプロトタイプが私の関数を完全に消去します。 幸い、別の方法で継承できます。



3.メソッドはオブジェクトリテラルを愛するすべての人に捧げられます



ここに彼は:



 function inherit_B(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype; var f = new F(); for (var prop in Child.prototype) f[prop] = Child.prototype[prop]; Child.prototype = f; Child.prototype.super = Parent.prototype; }
      
      





親のプロトタイプから継承者のプロトタイプにすべてのプロパティを取得してコピーするだけなので、私のお気に入りのオブジェクトリテラルは正常に機能します。



 $(document).ready(function () { function Man(name) { this.name = name } Man.prototype = { constructor: Man, THOUGHTS: "wanna beer!", say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'") } } function Gentleman(name, prefered_beverage) { Man.call(this, name); this.prefered_beverage = prefered_beverage; } Gentleman.prototype = { constructor: Gentleman, THOUGHTS: "it's teatime!" } inherit_B(Gentleman, Man) function Programmer(name, prefered_lang) { Gentleman.call(this, name, "Cofee"); this.prefered_lang = prefered_lang; } Programmer.prototype = { constructor: Programmer, THOUGHTS: "runtime error 138? wanna debug XD!" } inherit_B(Programmer, Gentleman) var man = new Man("Jack"); var gentleman = new Gentleman("John", "Orange pekoe"); var programmer = new Programmer("James", "C++"); man.say(); gentleman.say(); programmer.say(); });
      
      





そして、コンソールは私に同意します:



 sample.js:11 My name is Jack and i think:'wanna beer!' sample.js:11 My name is John and i think:'it's teatime!' sample.js:11 My name is James and i think:'runtime error 138? wanna debug!'
      
      





素晴らしい。 次に、多くの親クラスがあり、たとえば、2〜3クラスをオーバーロードしたメソッドを呼び出す必要があるという仮想的な状況を想像してください。 もちろん、このような状況では、アプリケーションのアーキテクチャを詳しく調べる方が良いでしょう。 ここで、意図したとおりにすべてが機能すると仮定します。たとえば、次のように書くのは面倒です。



 this.super.super.super.someMethod.apply(this)
      
      





4.しかし、それはまた解ける



 function inherit_C(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype; var f = new F(); for (var prop in Child.prototype) f[prop] = Child.prototype[prop]; Child.prototype = f; Child.prototype[Parent.prototype.__class_name] = Parent.prototype; }
      
      





この関数は、親プロトタイプを参照して、子プロトタイプにオブジェクトを追加します。 正常に機能させるには、各クラスのプロトタイプにフィールドを追加します



 __class_name
      
      





たとえば、BadProgrammerクラスが階層に表示され、遠い祖先のプロトタイプへの便利なアクセスが必要だったとします。 前の例を少し変更します。



 $(document).ready(function () { function Man(name) { this.name = name } Man.prototype = { __class_name: "Man", constructor: Man, THOUGHTS: "wanna beer!", say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'") } } function Gentleman(name, prefered_beverage) { Man.call(this, name); this.prefered_beverage = prefered_beverage; } Gentleman.prototype = { __class_name: "Gentleman", constructor: Gentleman, THOUGHTS: "it's teatime!" } inherit_C(Gentleman, Man) function Programmer(name, prefered_lang) { Gentleman.call(this, name, "Cofee"); this.prefered_lang = prefered_lang; } Programmer.prototype = { __class_name: "Programmer", constructor: Programmer, THOUGHTS: "runtime error 138? wanna debug XD!" } inherit_C(Programmer, Gentleman) function BadProgrammer(name) { Programmer.call(this, name, "brainfuck"); } BadProgrammer.prototype = { __class_name: "BadProgrammer", constructor: BadProgrammer, THOUGHTS: "runtime error 138? wanna debug XD!", say: function () { this.THOUGHTS = this.Man.THOUGHTS; this.Man.say.apply(this); } } inherit_C(BadProgrammer, Programmer) var man = new Man("Jack"); var gentleman = new Gentleman("John", "Orange pekoe"); var programmer = new Programmer("James", "C++"); var badprogrammer = new BadProgrammer("Jake"); man.say(); gentleman.say(); programmer.say(); badprogrammer.say(); });
      
      





BadProgrammerクラスは、進化するクラスチェーンの最初のリンクの考えを利用しましたが、今ではプログラマが通常考えていることについてはまったく考えていません;)



 My name is Jack and i think:'wanna beer!' My name is John and i think:'it's teatime!' My name is James and i think:'runtime error 138? wanna debug!' My name is Jake and i think:'wanna beer!'
      
      





5.そして、何か他のもの



どんな場合でもこれが便利になるとは思いませんが、いつか誰かが多重継承を必要とするかもしれません。 以下を実装することも可能です。



 function inhertit_multiple(child) { for( var i = 1; i < arguments.length; ++i ) { var parent = arguments[i] for (var prop in parent.prototype) { if (!child.prototype[prop]) child.prototype[prop] = parent.prototype[prop]; } child.prototype[parent.prototype.__class_name] = parent.prototype; } }
      
      





以前のバージョンとあまり変わらない。

それがどのように機能するかを示すために、私は別の完全に現実的な例を思いつきました:



 $(document).ready(function () { function Mammy() { this.mammy_message = "You Dont love me!" } Mammy.prototype = { __class_name: "Mammy", say_something_wise: function () { console.log(this.mammy_message) } } function Daddy() { this.daddy_message = "I just don't want to be a dad!" } Daddy.prototype = { __class_name: "Daddy", say_something_wise: function () { console.log(this.daddy_message) } } function Lad() { this.lad_message = "And i want a candy!"; Mammy.apply(this); Daddy.apply(this); } Lad.prototype = { __class_name: "Lad", say_something_wise: function () { this.Daddy.say_something_wise.call(this); this.Mammy.say_something_wise.call(this); console.log(this.lad_message); } } inhertit_multiple(Lad, Mammy, Daddy) var lad = new Lad(); lad.say_something_wise(); });
      
      





これを実行すると、コンソールには期待どおりのものが表示されます



 I just don't want to be a dad! You Dont love me! And i want candy!
      
      







それがすべての仕組みです。 ここにすべてのコードと例を記載します -これは便利です。



UPD。 一人の良い人が正しく言ったように、最初のメソッドを除くすべてのメソッドで、instanceofはクラスを親クラスのインスタンスとして認識することを拒否します。 多重継承により、この欠点は持続しましたが、他のケースではそれを排除しました。



All Articles