JavaScriptのclass構文について考える

はいどーも三が日も最後ですねこんにちは。
本日はJavaScriptのclass構文について考えてみます。
ただしあくまでも考えているだけなので、内容の正確さは保証しません。

class構文にできてコンストラクタ関数でできないこと

ES5以前のJavaScirptでは、クラス(と考えても差し支えのない機能)を作る際にはコンストラクタ関数を利用していました。
ES6でも使えますが、ES6を使うならclass構文を使いたいですよね。
ちなみにですが、RPGツクールMVのコアスクリプトは軒並みコンストラクタ関数で宣言されていますが、class構文も使うことができますよ。

さてclass構文にできてコンストラクタ関数にできないことは一体なんでしょうか?
僕がぱっと思いついたのは、static修飾子の利用です。
ES5以前の場合、静的メソッドは継承が七面倒なことになります。
何が面倒と言って、いわゆる「クラスっぽい継承」を実装するのにJavaScriptではprototypeプロパティを使っているわけですが、staticなメソッドはこのprototypeプロパティを介さないのですね。
つまりstaticなメソッドは一手間加えないと継承されません。

それがclass構文なら、単にstatic修飾子を付加するだけでちゃんと継承してくれます。
これは便利ですね。
プロトタイプベースよりはクラスベースのオブジェクト指向プログラミングに慣れている方(こっちのが大多数と思いますが)は、ES5に縛られずES6のclass構文をガンガン使うとよいんじゃないでしょーか。

コンストラクタ関数にできてclass構文にできないこと

では逆にコンストラクタ関数にできてclass構文にできないことは何でしょうか?
僕がぱっと思い浮かんだのは「コンストラクタ関数を宣言した場所とはまったく別の場所でメソッドを追加すること」でした。

RPGツクールMVでプラグインを作るとき、よく以下のような書き方をして関数をオーバーライドしますよね。

また、コアスクリプトに新たなメソッドを追加する際も、似たような感じになります。

しかしこれ、クラス構文っぽくないですよね。
実際、コンストラクタ関数のprototypeプロパティに関数を追加しているだけです。

ではクラス構文で動的にメソッドを追加したり、上書きするにはどうすればよいのか?
軽く調べたのですが、どうも無理っぽい気がします。
つまり、あくまでもclass構文は静的な構造を提供するのであって、従来のコンストラクタ関数のように動的な構造は提供しない、ということではないでしょーか。

いやあんまり自信ないんで間違ってたらメンゴですよ。

なお、クラス構文で書かれたクラスも、従来の方法で動的にメソッドを追加することは可能です(class構文はコンストラクタ関数で作る「クラス風機能」の糖衣構文のため)。
僕もよくやってます。

C#との比較

おまけでC#と比較してみましょう。
C#において、既存のクラスに対して動的にメソッドを追加すると言えば、拡張メソッドが思い浮かびます。
ただ拡張メソッドの実態はstaticクラスの静的メソッドであって、既存のクラスに対して本当にメソッドを追加しているわけではありません。

一方でJavaScriptのprototypeプロパティへの関数の追加は、本当に既存のクラスに対してメソッドを追加しています。
すなわち、コンストラクタ関数から生成されたインスタンスは、コンストラクタ関数が持つprototypeプロパティに対して暗黙的にアクセスできるのです。
ツクールMVでは__proto__を介してますね。

僕的にはJavaScriptのclass構文でも拡張メソッド的なことができたら嬉しいなあとか思ったのですが、それだったら従来通りprototypeプロパティに色々追加していけば問題ないじゃんということでしょうし、多分そっちのほうがJavaScriptっぽいんですかね。
この辺は詳しくないのでわかりませんが、似たようなことを実現するのにも言語によって全然変わるのがプログラミングの面白いところだなあと思いました。

ほなそんな感じで今日は終わります。
そして正月も終わります。
またね。

フォローする