この記事の内容
- 独自なオブジェクト(他言語のclassに相当するもの)の作り方
- オブジェクト指向プログラミングにおける「継承」をJavaScriptではどのようにするか
目次
(1) 学習環境の構築と基本的な書き方
(2) 変数とデータ型
(3) 演算子および配列
(4) 制御構文と関数
(5) 関数の応用1
(6) 関数の応用2
(7) オブジェクトの基礎
(8) JavaScriptのオブジェクト指向プログラミング1 概要
(9) JavaScriptのオブジェクト指向プログラミング2 オブジェクトの作り方と継承 <-- この記事の内容
(10) JavaScriptのオブジェクト指向プログラミング3 多態性
(11) JavaScriptのオブジェクト指向プログラミング4 カプセル化
(12) ES6の新機能について
独自なオブジェクトの作り方
前回の内容のように、 ES5までの JavaScriptでは、classというキーワードが存在しない。既に用意されているオブジェクトを受け継いで新しいオブジェクトを作る形になる。
組み込みオブジェクトという、JavaScriptで最初から用意されているオブジェクトの使い方を前回の記事で観てきた。今回は、独自なオブジェクトを作る方法について観ていく。
クラス(となるもの)の作り方
7回目の記事の内容どおりにコーディングしても構わないが、よりオブジェクト指向プログラミングらしく記述する方法として、クラスに該当するオブジェクト(いわば、見本となるオブジェクト)を function
で定義してしまう、という方法がある。
var Dog = function() {
};
var pochi = new Dog();
var shiro = new Dog();
上記の例は、 Dog
というクラス(見本のオブジェクト)を作ったことになる。この Dog
オブジェクトを見本として、 pochi
と shiro
いうオブジェクトを生成している。Javaでいうところの、
Dog pochi = new Dog();
Dog shiro = new Dog();
これを実行したようなものである。
プロパティの定義とコンストラクタ(となるもの)の利用
オブジェクトの特徴のうち、プロパティにあたるものの初期値の設定には、 this
キーワードを利用する。
var Dog = function(name) {
this.name = name;
};
var pochi = new Dog('ポチ');
var shiro = new Dog('シロ');
console.log(pochi.name); // ポチ と表示される
console.log(shiro.name); // シロ と表示される
Dog
に name
(名前)の属性を追加し、 pochi
には「ポチ」という名前をつけている。このように、functionの引数に値を与えて、 this
キーワードでプロパティを設定することができる。このような方法によるプロパティの設定は、いうなれば「コンストラクタ」である。
メソッドの定義
Dog
に bark
というメソッドを追加してみる。メソッドも同じように this.メソッド名 = function() {...}
と記述して指定することができる。
var Dog = function(name) {
this.name = name;
this.bark = function() {
console.log(this.name + "が吠える:ワン!");
};
};
var pochi = new Dog('ポチ');
var shiro = new Dog('シロ');
pochi.bark(); // ポチが吠える:ワン! と表示される
shiro.bark(); // シロが吠える:ワン! と表示される
この他に、もうひとつ、メソッドを定義する方法がある。それは、見本オブジェクトがもつ prototype
というプロパティを利用する。
(見本の)オブジェクト名.prototype.メソッド名() = function() {
// 以下に処理を記述する
}
利用例を、以下に示す。
var Dog = function(name) {
this.name = name;
};
Dog.prototype.bark = function() {
console.log(this.name + "が吠える:ワン!");
}
var pochi = new Dog('ポチ');
var shiro = new Dog('シロ');
console.log(pochi.name); // ポチ と表示される
console.log(shiro.name); // シロ と表示される
pochi.bark(); // ポチが吠える:ワン! と表示される
shiro.bark(); // シロが吠える:ワン! と表示される
メソッドの定義は、このようにして行う。
※なお、prototype
でプロパティを設定することも可能。サンプルコードは省略。
継承
オブジェクト指向プログラミングにおける3つの特徴として、以下のものがある。
- 継承(Inheritance)
- 多態性(Polymorphism)
- カプセル化(Encapsulation)
以降、これらをJavaScriptでどのように記述すれば実現できるかを観ていく。まずは継承。
先ほどは Dog
という見本オブジェクトを作成したが、もう少し抽象的な見本オブジェクトとして Animal
を作って、それを継承する Dog
と Cat
のオブジェクトを作ってみる。
var Animal = function(name, voice) {
this.name = name;
this.voice = voice;
}
Animal.prototype.bark = function() {
console.log(this.name + "が鳴く:" + this.voice);
}
var Dog = function() {
}
var Cat = function() {
}
プロパティの継承
Animal
は name
(名前)と voice
(鳴き声)のプロパティを持っているとする。このとき Dog
や Cat
が Animal
を継承して、この2つのプロパティを持たせたい場合、以前の記事で紹介した call
もしくは apply
のメソッドを利用する。おさらいすると、どちらのメソッドも、引数で指定したオブジェクトに、自分が持っているメソッドを貸し出して、すぐ実行してもらうというものである。
var Animal = function(name, voice) {
this.name = name;
this.voice = voice;
}
Animal.prototype.bark = function() {
console.log(this.name + "が鳴く:" + this.voice);
}
var Dog = function(name) {
Animal.call(this, name, "ワン!");
}
var Cat = function(name) {
Animal.call(this, name, "ニャー!");
}
var pochi = new Dog("ポチ");
var tama = new Cat("タマ");
console.log(pochi.name); // ポチ と表示される
console.log(tama.name); // タマ と表示される
Dog
および Cat
のコンストラクタ部分で Animal
オブジェクトの call
メソッドを実行し、Animal
のコンストラクタを実行している。このように記述することで、name
と voice
のプロパティを継承することができる。
メソッドの継承
では、JavaScriptでメソッドの継承を実現するにはどうするかというと、プロトタイプチェーンというものを利用する。プロトタイプチェーンは、プロトタイプを次々にさかのぼって参照・実行することが出来る仕組みである。
つまり、Dog
や Cat
それぞれで、プロトタイプに Animal
のプロトタイプを指定してあげれば良い。
var Animal = function(name, voice) {
this.name = name;
this.voice = voice;
}
Animal.prototype.bark = function() {
console.log(this.name + "が鳴く:" + this.voice);
}
var Dog = function(name) {
Animal.call(this, name, "ワン!");
}
Dog.prototype = new Animal;
var Cat = function(name) {
Animal.call(this, name, "ニャー!");
}
Cat.prototype = new Animal;
var pochi = new Dog("ポチ");
var tama = new Cat("タマ");
pochi.bark(); // ポチが鳴く:ワン! と表示される
tama.bark(); // タマが鳴く:ニャー! と表示される
プロトタイプの指定は、上記のコードでは、この部分。
Dog.prototype = new Animal;
子供のオブジェクト名.prototype = new 親のオブジェクト名;
と記載する(親のオブジェクト名の後ろに括弧は不要)。こうすることで、Dog
にわざわざ bark
メソッドの定義を記述しなくても、親である Animal
のプロトタイプにさかのぼって内容を参照し、bark
メソッドが実行される。
次回予告
多態性