Ext JSでのOverrideについて

この記事は、 Sencha Advent Calendar 2012 の5日目の記事です。皆さんも是非参加してください。 明日も明後日も決まってないみたいなんで、誰か書いてくださいよ〜 そこの、青さん!蛙さん!たのみますよ。

通常、クラスを理解するプログラマがオーバーライドという言葉を聞くと、親クラスを継承した中でクラスのメソッドをオーバーライドするというのをイメージすると思います。 通常のクラスシステムでは考えられないことだと思いますが、JavaScript上で実現されているフレームワークであるExt JSのクラスシステムでは、既存のクラスの定義内容をあとから変更することができます。 Ext JSでは、このこともオーバーライドと呼びます。

通常のオーバーライドでは、クラスを継承してメソッドをオーバーライドしますので、 オーバーライドしたメソッドを呼び出すためには、継承したサブクラスをインスタンス化しなければなりません。 ここで扱うオーバーライドは、元のクラス定義そのものにあるメソッドをオーバーライドするということになります。 その場合、元のクラスをインスタンス化したとしても、オーバーライドしたメソッドが実行されます。

この機能は、Ext JS本体のバグを修正するためのパッチとか、一部特定の場合だけメソッドの挙動を変える必要があるときなどに使われます。 また、Ext JSで提供されているロケールファイルの中身は、このオーバーライドのオンパレードです。 この機能は、以前から、Ext.overrideメソッドとして提供されていました。 しかし、オーバーライドしたメソッドから、元のメソッドを呼び出すようなことはできませんでした。 Ext JS 4.1からは、元のメソッドを呼び出せるようになったので、パッチ当ての時に元のメソッドと重複したコードを書かずに済む場面が増えることでしょう。 また、同じくExt JS 4.1からは、Ext.overrideメソッドだけではなく、Ext.defineメソッドを使ったオーバーライドもできるようになりました。 ここでは、Ext.defineを使ったオーバーライドについてみていきましょう。

[js] // Base Class Ext.define(‘My.BaseClass’, { method: function(v) { console.log(‘ベースクラスのメソッド’); } }); // Class を継承 Ext.define(‘My.SubClass’, { extend: ‘My.BaseClass’, method: function(v) { console.log(‘サブクラスのメソッド’); } }); [/js]

これは、普通の継承です。 ここで、

[js] var c1 = Ext.create(‘My.SubClass’); c1.method(); [/js]

とすれば、コンソールには、「サブクラスのメソッド」と表示されます。 生成するクラスを"My.BaseClass"にした場合は、「ベースクラスのメソッド」とログされます。 ここまでは普通です。

[js] // オーバーライド Ext.define(‘My.OvrClass’, { override: ‘My.BaseClass’, method: function(v) { console.log(‘オーバーライドしたメソッド’); } }); [/js]

次にこのように、extend指令の代わりにoverride指令を加えます。 こうすると、クラスを継承するのではなく、クラス定義そのものを上書きするという挙動になります。 第1引数に渡すクラス名は、ここでは意味を持ちません。 つまり、この定義をして、

[js] Ext.create(‘My.OvrClass’); [/js]

とインスタンス化しようとしてもエラーになります。 なんで、ここでクラス名を指定するかというと、それはExt.Loaderに見つけてもらうため。その為です。 オーバーライドされたクラスを使いたい別のクラスにおいて、requiredの中にこのクラス名(クラス名じゃないんですが)を入れておくとExt.Loader様がロードしてくださるわけです。

このようにオーバーライド定義をすると、

[js] var c1 = Ext.create(‘My.BaseClass’); c1.method(); [/js]

と、My.BaseClass をインスタンス化した場合に、「オーバーライドしたメソッド」とログされます。 元のメソッドを呼び出すときには、クラス継承したときに親クラスのメソッドを呼び出すときと同様、 callParentを使います。

[js] // オーバーライド Ext.define(‘My.OvrClass’, { override: ‘My.BaseClass’, method: function(v) { this.callParent(v); console.log(‘オーバーライドしたメソッド’); } }); [/js]

尚、このオーバーライドは、サブクラスでも適用されます。BaseClassがオーバーライドされていて、SubClassがBaseClassを継承している場合に、SubClassをインスタンス化してメソッドを呼び出すと、オーバーライドされたメソッドが実行されます。

1 thought on “Ext JSでのOverrideについて

コメントは停止中です。