Backboneで多重継承を実現する

やりたいこと

  • Viewとか、Modelとか、機能に意味を持たせて開発をしていたときに、複合した機能を持つ具象クラスを作りたくなった。

 Backboneのextendメソッドは、親→子の単一継承をサポートするのみです。例えば以下です。

var extendedModel = Backbone.Model.extend({
    parse: function(hoge){
        console.log("parse!");
        return hoge;
    }
});

 しかし、Javaのインターフェースのように、複数のクラスを継承したい場合に、以下のようにしたくてもうまくいきません。

var extendedModelA = Backbone.Model.extend({
    parse: function(hoge){
        console.log("parse!");
        return hoge;
    }
});


var extendedModelB = Backbone.Model.extend({
    url: function(hoge){
        console.log("url!");
        return "..."
    }
});


var model = extendedModelA.extend(extendedModelB);  // error

 どうしても、model.fetch時に以下のようなログを吐きたい!

url!
parse!

解決策

オブジェクトを順に継承していく

 単純明快。

var modelObjectA = {
    parse: function(hoge){
        console.log("parse!");
        return hoge;
    }
};

var modelObjectB = {
    url: function(hoge){
        console.log("url!");
        return "..."
    }
};

var model = Backbone.Model.extend(modelObjectA).extend(modelObjectB);

prototypeを継承する

 以下のような方法もあります。場合によってはmodelObjectの継承よりもわかりやすくなります。

var extendedModelA = Backbone.Model.extend({
    parse: function(hoge){
        console.log("parse!");
        return hoge;
    }
});


var extendedModelB = Backbone.Model.extend({
    url: function(hoge){
        console.log("url!");
        return "..."
    }
});


var model = extendedModelA.extend(extendedModelB.prototype);

多重継承の問題点

 Javaのimplementsと違い、各々のAbstractClassがメソッドに処理を持っていますから、それらを上手くチェーンして処理するようなプログラムを書くことは簡単ではありません。

 可能な限り使わないようにするか、どうしても必要な場合は、規約で縛って(共通機能をオーバーライドしない)運用することをお勧めします。

 「共通メソッド」を使いたいだけなら、utilクラスを定義したり、やり方はいくらでもあります・・・。

まとめ

 そもそも、Backbone自体がそろそろ人気も落ち着いてきている感じなので、フロントエンドの現場で使うことはあまりないと思いますが、こういった工夫を凝らすことで、うまく付き合っていきたいものですね。