継承…してあげるんだからねっ!

引き続き、オブジェクトのお話をまだまだしていくぞ。

まだあんの?

まだまだ。もう腹をくくるんだな


継承ねぇ

もうわかったよ。やるよ。やればいいんでしょ

今回はオブジェクトの継承についてやっていこう

前回、プロトタイプチェーンという話をした。
・最終的にObjectのprototypeを参照する。
・Objectは全てのオブジェクトの親である
こんな感じだ。
で、チェーンは
1:インスタンス化したメソッド参照
2:インスタンス元のprototype
3:Objectクラスのprototype
の順番だったが、Objectクラスのprototypeを見に行く前にさらに別オブジェクトのprototypeのものを
参照する事ができるのだ。
そうする事を継承と呼ぶ

はっはーん。なるほど、分からん

こいつも実際にやってみたほうが分かりやすいかな。

Object.prototype.myMethod = function(){ alert('あのう。Objectから呼ばれたんですけどぉ'); }

// 使いたいオブジェクト
var myObj = function()
{
 this.name;
 this.spellCard;
}

// 継承されるオブジェクト
var myObj2 = function()
{
 this.saySpellCard = function ()
 {
  alert(this.name+'「スペルカード! '+this.spellCard+'」');
 }
}

// プロトタイプにインスタンス化する事で継承。順番に注意!!
myObj.prototype = new myObj2();
myObj.prototype.sayName = function ()
{
 alert(this.name+'のターン');
}

var chiruno = new myObj;

// プロパティの設定
chiruno.name      = 'チルノ';
chiruno.spellCard = 'アイシクルフォール!';

// メソッドの実行
chiruno.sayName();      // myObjのprototype
chiruno.saySpellCard(); // myObj2のメソッド(継承したもの)
chiruno.myMethod();     // Object暮らすのprototype

ううむ。なんかごちゃごちゃしてきたね

順番に見ていこう
まず、オブジェクトが2つ作られているのはわかるな。

そだね。そこは大丈夫

次に、使いたいオブジェクトのprototypeに継承されるオブジェクトがまんまインスタンス化されている。
prototypeは順番に参照されるので、ここに新しく入れてやる事で、使用する事ができるってわけだ。
順番に注意!と書いてあるがこれは本当に注意だ。
myObj.prototypeの中をmyObj2のメソッドで上書きしている事になる。
myObj.prototype.sayNameを先に入れておくとこんな事が発生する。

myObj.prototype.sayName = (略) // sayNameメソッドはあるよ
myObj.prototype = new myObj2(); // 全部上書きするね!
myObj.prototype.sayNameは上書きされてなくなる

なので、順番に注意!とはこの事なんだ

後にすれば、後のメソッドを追加するから、myObj2のは大丈夫って事か
でも、myObj2の中にも、sayNameがあったらそれは上書きされるんだよね。
名前が一緒だから実行方法は同じでも
myObj2の処理じゃなくて、追加したやつになるって事だよね

その通り、名前の付け方には注意が必要だ

メソッド実行部分はまぁそのままなので割愛するが
この例の場合の各メソッドが実行されるチェーンについてはこうなっている。

■sayNameメソッド
1:インスタンス化された中身を探す。
↓無かった
2:インスタンス元のprototypeを見てみる
→あった!実行

■saySpellCardメソッド
1:インスタンス化された中身を探す。
↓無かった
2:インスタンス元のprototypeを見てみる
↓無かった
3:継承したmyObj2のprototypeを見てみる
→あった!実行

■myMethodメソッド
1:インスタンス化された中身を探す。
↓無かった
2:インスタンス元のprototypeを見てみる
↓無かった
3:継承したmyObj2のprototypeを見てみる
↓無かった
4:Objectクラスのprototypeを見てみる
→あった!実行

継承しているから探しに行く回数も増えているね

特にObjectクラスに追加したやつは一番大変だな。

って事は、myObj2の中でもmyObj3みたいなのを作って継承させてたら
myObjの中でもmyObj3のが使えたりしてーみたいな。まさかね

使えるんだな。これが

使えんのかよ

Object.prototype.myMethod = function(){ alert('あのう。Objectから呼ばれたんですけどぉ'); }

// 使いたいオブジェクト
var myObj = function()
{
 this.name;
 this.spellCard;
}

// 継承されるオブジェクト
var myObj2 = function()
{
 this.saySpellCard = function ()
 {
  alert(this.name+'「スペルカード! '+this.spellCard+'」');
 }
}

// myObj2内で継承されるオブジェクト
var myObj3 = function()
{
 this.winWord;
 this.sayWinWord = function ()
 {
  alert(this.winWord);
 }
}

// myObj2に継承
myObj2.prototype = new myObj3();


// プロトタイプにインスタンス化する事で継承。順番に注意!!
myObj.prototype = new myObj2();
myObj.prototype.sayName = function ()
{
 alert(this.name+'のターン');
}

var chiruno = new myObj;

// プロパティの設定
chiruno.name      = 'チルノ';
chiruno.spellCard = 'アイシクルフォール!';
chiruno.winWord   = 'あたいったら最強ね!';

// メソッドの実行
chiruno.sayName();      // myObjのprototype
chiruno.saySpellCard(); // myObj2のメソッド(継承したもの)
chiruno.sayWinWord(); // myObj2のメソッド(継承したもの)
chiruno.myMethod();     // Object暮らすのprototype

うお…まじだ…

きちんとmyObj3のプロパティにもアクセスできているね
親の親だから、じいちゃんばぁちゃんオブジェクトだね。

そう、こんな風にどんどん継承していくことができるのだ。

でもこれ、ちゃんと考えて作らないと大変な事になる気がするんだけど

例えば?

こうなった場合さ、さっきけーねがチェーンの順番を解説してくれたじゃん
そこに一つ追加されて、最後のObjectクラスのprototypeに辿り着くまで、長くなっちゃうよねと思って
だから、むやみに継承しまくってたら、JSの中の人探すのめっちゃ大変じゃん

その通りだ!!!後はやたらコードがごちゃごちゃして分からんって事もありうる
この辺は設計時にきちんと決めるべきところだな
今日は冴えてるじゃないか

アタイですから

まったく。まぁいい

さぁ、ここまでくれば分かるだろう。
良く書かれている言葉

【javascriptはプロトタイプベースのオブジェクト指向言語である!】

だ。

そだね!
あんだけ共通化だなんだやったし、継承もプロトタイプにブチ込んでるし
今なら、その言葉聞いても
「まさにその通り!!!」って自信持って言えるよ

まぁ、まだ細々した所は続いていくと思うが、一つの大きな壁を超えられたようだ。
今回はここまでにしよう

けーねありがとう!