下記の例でJSの継承手法を解説していきたいと思います
※下記の文章を読めるにはオブジェクトのプロトタイプ知識が必要となります
会員システム
動画配信サイトには2種類の会員があります:
- 一般会員
- 属性:ユーザー名、パスワード
- メソッド:無料動画の視聴
- プレミアム会員
- 属性:一般会員のすべての属性、会員の有効期限
- メソッド:一般会員のすべてのメソッド、有料動画の視聴
これらの要件を満たすために、コンストラクタをどのように書けばよいでしょうか?
// 一般会員のコンストラクタ
function user(username, password) {
this.username = username;
this.password = password;
}
User.prototype.playFreeVideo = function() {
console.log('無料動画を視聴する');
}
// プレミアム会員のコンストラクタ
function premiumUser(username, password, expires) {
this.username = username;
this.password = password;
this.expires = expires;
}
premiumUser.prototype.playFreeVideo = function() {
console.log('無料動画を視聴する');
}
premiumUser.prototype.playPremiumVideo = function() {
if (this.expires > new Date()) { //動作しないコード 今の日付の意味で記載している
console.log('有料動画を視聴する');
}else{
console.log('プレミアム会員の有効期限が切れています');
}
}
上記のコードには2つの重複があります:
-
premiumUserのコンストラクタに含まれる重複コード
this.username = username; this.password = password;
このコードはUserコンストラクタと同じです。将来も変わることはないでしょう。すなわち、一般会員が持つべき属性はプレミアム会員も必ず持つということです。
-
premiumUserのプロトタイプに含まれる重複コード
premiumUser.prototype.playFreeVideo = function() { console.log('無料動画を視聴する'); }
このメソッドはUser上の同名メソッドと全く同じです。将来も変わることはないでしょう。すなわち、一般会員が持つべきメソッドはプレミアム会員も必ず持つということです。
これらの重複をどのように解決するか?
コンストラクタ内部の重複を処理する
premiumUserコンストラクタを次のように書き換えることができます:
function premiumUser(username, password, expires) {
user.call(this, username, password);
this.expires = expires;
}
プロトタイプの重複を処理する
次の一文で完了です:
Object.setPrototypeOf(premiumUser.prototype, User.prototype);
これで、先に挙げた重複コードの問題を完璧に解決しました。
ほかデザインパターンで解決手法はありますが、また次回......
おまけ、JavaScriptで継承を封装する方法
function inherit(Child, Parent) {
// プロトタイプチェーンで継承を完了する
Object.setPrototypeOf(Child.prototype, Parent.prototype);
}