問題は写真にあります
問題を視覚化することから始めましょう。 2つの基本クラスがあり、それらから2つの子クラスが継承されているとします。
ある時点で、同じ機能の必要性が子クラスに現れます。 通常のコピーと貼り付けは、図では次のようになります。
多くの場合、この機能は親クラスとは関係がないため、基本クラスに配置することは非論理的で間違っています。 ミックスイン-別の場所に取り出してください。 言語の観点から見ると、ミックスインは共通のオブジェクトになる可能性があります。
それでは、記事全体が書かれた瞬間、つまりミックスインをクラスに適切に練り込む方法について説明しましょう。
私自身の経験に基づいて、最も便利な方法は、ミックスインに基づいて一時クラスを作成し、それを継承キューに置き換えることです。
このアプローチの長所
- 実装の容易さ。
- ミックスインに含まれるコードの再定義の容易さ。
- ミックスインを接続する柔軟性、難なくミックスインを作成する機能。
- コードで別のパターンを使用しても、既存の継承メカニズムが使用されるため、その理解とサポートを複雑にすることはありません。
- 介入の速度-この方法でミックスインをこねるのに単一のサイクルは必要ありません。
- 最適なメモリ使用量-何もコピーしません
コードを書く
以降のすべての例では、特定の実装( Backbone.Mixライブラリ)が使用されます。 コードを見ると、非常にシンプルであることがわかるので、お気に入りのフレームワークに簡単に適合させることができます。
実際の継承チェーンに埋め込まれたミックスインの使用方法を見て、実際にこのアプローチの利点を体験してみましょう。 あなたがサイトを書いていると想像してください))そしてあなたのサイトには、閉じることができるさまざまなものがあります-ポップアップ、ヒントなど。 彼らはすべて、CSSクラスを
close
て要素を非表示にして要素のクリックをリッスンする必要があります。 このためのミックスインは次のようになります。
var Closable = { events: function () { return { 'click .close': this._onClickClose }; }, _onClickClose: function () { this.$el.hide(); } };
介入します!!!
var Popup = Backbone.View.mix(Closable).extend({ // - });
とても簡単ですね。 これで、継承チェーンは次のようになります。
- 最初に基本クラス
Backbone.View
- 無名クラスはそれから継承され、そのプロトタイプは
Closable
-
Popup
のチェーンを完成させます
このようなスキームにより、混合先のクラスのミックスインからメソッドを再定義および再定義することが非常に簡単になります。 たとえば、閉じるときに
Popup
がコンソールに何かを書き込むようにできます。
var Popup = Backbone.View.mix(Closable).extend({ _onClickClose: function () { this._super(); console.log('Popup closed'); } });
以下、例では、 backbone-superライブラリを使用します
干渉しない不純物..
...しかし、彼らは助けます。 時々、こねるのは弱くなく、1つのミックスインが不可欠です。 たとえば、私たちがカッコイイ人で、IndexedDBにログを書き込むと想像してください。また、このための独自の
Loggable
があります
Loggable
var Loggable = { _log: function () { // IndexedDB } };
次に、ポップアップによって2つのミックスインに干渉します。
var Popup = Backbone.View.mix(Closable, Loggable).extend({ _onClickClose: function () { this._super(); this._log('Popup closed'); } });
構文は複雑ではありません。 図では、次のようになります。
ご覧のように、継承チェーンは、ミックスインを接続する順序に応じて整列します。
依存ミックスイン
今、私たちのアナリストが私たちに近づき、ポップアップ、ヒントのすべての閉鎖に関する統計を閉じたいと言っている状況を想像してください。 もちろん、サイトで登録を行ったときから、そのような場合の
Trackable
は長い間ありました。
var Trackable = { _track: function (event) { // - } };
Trackable
と
Closable
をリンクしたい、あるいは
Closable
依存する必要があるのは驚くことではありません。 この図では、次のようになります。
そして、継承チェーンでは、
Trackable
は
Closable
よりも前にある必要があり
Closable
。
依存関係を持つミックスインのコードは少し複雑になります。
var Closable = new Mixin({ dependencies: [Trackable] }, { events: function () { return { 'click .close': this._onClickClose }; }, _onClickClose: function () { this.$el.hide(); this._track('something closed'); // <- } });
しかし、それほど複雑ではありません。依存関係を記述できる場所ができました。 これを行うには、追加のラッパークラスである
Mixin
を導入する必要があり、
Mixin
自体は単なるオブジェクトではなく、このクラスのインスタンスになりました。 この場合、mixin接続自体は変更されないことに注意してください。
var Popup = Backbone.View.mix(Closable, Loggable).extend({ … });
ミックスインを正しくドキュメント化する
WebStormは優れたミックスインをサポートしています。 JSDocを正しく記述すれば十分であり、プロンプト、オートコンプリート、コードの一般的な構造の環境による理解が大幅に向上します。 環境は、タグ
@mixin
および
@mixes
理解します。 文書化されたClosable
Closable
および
Popup
クラスの例を見てみましょう。
/** * @mixin Closable * @mixes Trackable * @extends Backbone.View */ var Closable = new Mixin({ dependencies: [Trackable] }, /**@lends Closable*/{ /** * @returns {object.<function(this: Closable, e: jQuery.Event)>} */ events: function () { return { 'click .close': this._onClickClose }; }, /** * @protected */ _onClickClose: function () { this.$el.hide(); this._track('something closed'); } }); /** * @class Popup * @extends Backbone.View * @mixes Closable * @mixes Loggable */ var Popup = Backbone.View.mix(Closable, Loggable).extend({ /** * @protected */ _onClickClose: function () { this._super(); this._log('Popup closed'); } });
多くの場合、特定の祖先を持つクラス用にミックスインが作成されます。
Backbone.View
から継承されたクラス用に記述された
Closable
、決して例外ではありません。 この状況では、
@extends
明示的に指定しない限り、環境はこの先祖のメソッド呼び出しがmixinコードのどこから来たかを理解しません。
/** * @mixin Closable * @mixes Trackable * @extends Backbone.View */ var Closable = new Mixin(...);
これで、おそらくすべて、幸せな介入!
私のブログの英語版
Backbone.Mixライブラリ
同じ作者による別のコード: backbonex
ミックスインを思いつくときにjQueryヌードルをどのように見せるか? 英語で すぐにコード
私のtwitter (プロコードのみ)