JavaScript⑤・オブジェクト指向
オブジェクト指向
JavaScriptはオブジェクト指向言語ですが,ES6以前は クラス という概念が存在せず, プロトタイプ と呼ばれる概念が用いられてきました. ES6では,クラス の概念が導入されるなど,オブジェクト指向の機能が大幅に改良され, JavaやC#などの他のプログラミング言語と同様なオブジェクト指向の実装が可能になりました. ここでは,ES6のオブジェクト指向に注目して解説します.
CodePenの準備
CodePenにアクセスして,Penを作成し,タイトルを設定しましょう. Penのタイトルは「Chapter7」に設定しましょう.
クラスの定義
オブジェクト指向は,その名が示しているように,
「もの(オブジェクト)」を基準として実装する考え方です.
一般に,オブジェクトの型となるのが,クラス とみなすことができます.
ここでは,会話可能な Robot クラスを定義することを考えましょう.
クラスには,プロパティとメソッドを定義します. プロパティは,クラスに紐付けられた「変数」, メソッドは,クラスに紐付けられた「関数」のことを指します (正確にはクラスを実体化したインスタンスに紐付けられます).
Robotクラスには,nameプロパティ,constructorメソッド,helloメソッドを定義しています.
このうち,constructorは特殊なメソッドで,newを用いてRobotクラスの実体を作成するときに実行されます.
作成された実体のことを インスタンス と呼びます.
constructorでは,nameプロパティに引数で渡された値を設定しています.
このとき,this.nameはクラスに紐付けられたプロパティであり,
nameはメソッドに渡された引数であることに注意してください.
helloでは,nameプロパティの値を引用した文字列を出力しています.
プロパティであることを明確にするためにthis.nameと記述していますが,
引数として同じ名前のnameを受け取っていなければ,
単にnameと記述しても問題ありません(引数と混同を避けるためthis.nameを推奨).
// Robotクラスを定義
class Robot{
// constructorメソッド
constructor(name){
// nameプロパティに代入
this.name = name;
}
// helloメソッド
hello(){
document.write(`<p>Hello, my name is ${this.name}!</p>`);
}
}
Robotクラスのインスタンスをnewを用いて作成します.
このとき,constructorメソッドが呼び出され,
引数として渡されたRobinが,nameプロパティに代入されます.
// インスタンスの作成
let robin = new Robot("Robin");
インスタンスに紐付けられているプロパティにはドット記法でアクセスします.
ここでは,robin.nameで表します.
// nameプロパティ
document.write(`<p>robin.name=${robin.name}</p>`);
インスタンスに紐付けられているメソッドにもドット記法でアクセスします.
ここでは,robin.hello()で表します.
// helloメソッド
robin.hello();
クラスの継承
オブジェクト指向では,クラスを 継承 することで,既存のクラスを効率良く再利用することが可能です. ここでは, じゃんけん(Rock, Paper, Scissors) ができるRPSRobotクラスを, Robotクラスを継承して作成しましょう.
クラスを継承するには,extends を用います.
継承元となるクラスは スーパークラス や 基底クラス と呼ばれます.
継承することで,スーパークラスのプロパティとメソッドを定義することなく利用できます.
ここでは,nameプロパティやhelloメソッドが該当します.
また,constructorメソッドは,superでスーパークラスのconstructorメソッドを呼び出しています.
RBSRobotクラスでは,新たにageプロパティとrpsメソッドを定義しています.
rpsでは,0,1,2の乱数に基づき,
グー(Rock),チョキ(Scissors),パー(Paper)を出力します.
また,helloメソッドをオーバライド(上書き)して,年齢(age)を出力しています.
super.hello()はスーパクラスのhelloメソッドを表しています.
// RPCRobotクラスを定義
class RPSRobot extends Robot{
// constructorメソッド
constructor(name, age){
super(name);
// ageプロパティに代入
this.age = age;
}
// helloメソッドのオーバライド
hello(){
super.hello();
document.write(`<p>I'm ${this.age} years old.</p>`);
}
rps(){
let r = Math.floor(Math.random() * 3);
let hand;
switch(r){
case 0:
hand = "Rock";
break;
case 1:
hand = "Paper";
break;
case 2:
hand = "Scissors";
break;
}
document.write(`<p>My hand is ${hand}!</p>`);
}
}
RPSRobotクラスのインスタンスをnewを用いて作成します.
このとき,Robotクラスのconstructorメソッドが呼び出され,
引数として渡されたEmmaが,nameプロパティに代入されます.
// インスタンスの生成
let emma = new RPSRobot("Emma", 5);
RPSRobotクラスでは,Robotクラスで定義したhelloメソッドと,
独自に定義したrpsメソッドを呼び出すことが出来ます.
// helloメソッド
emma.hello();
// rpsメソッド
emma.rps();
オブジェクト・リテラル
オブジェクト・リテラルで定義
クラスと同様の機能を オブジェクト・リテラル でも実現可能です.
オブジェクト・リテラルでは,プロパティをプロパティ名:値,
また,メソッドをメソッド名(){}として定義します.
ここでは,nameプロパティとageプロパティ,そして,helloメソッドを定義しています.
let david = {
"name": "david",
"age": 3,
hello(){
document.write(`<p>Hello, my name is ${this.name}!</p>`);
document.write(`<p>I'm ${this.age} years old.</p>`);
}
}
クラスと同様にオブジェクトのプロパティとメソッドへのアクセスはドット記法を用います.
david.hello();
JSONへの変換
インスタンスやオブジェクトに紐付けられたプロパティは,
JSON.stringify()でJSON(JavaScript Object Notation)に変換可能です.
JSONでは全てのデータが文字列として表現されます.
ただし,メソッドはJSONに変換できないので注意が必要です.
ここでは,nameプロパティとageプロパティがJSONに変換されていることが確認できます.
// オブジェクトからJSON文字列に変換
let json = JSON.stringify(david);
document.write(`<p>json=${json}</p>`);
逆にJSONからオブジェクトに,JSON.parse()で変換することも出来ます.
変換されたオブジェクトは連想配列としても扱うことができます.
// JSON文字列からオブジェクトに変換
let obj = JSON.parse('{"name":"Ken", "age":20}');
document.write(`<p>obj.name=${obj.name}</p>`); // -> Ken
document.write(`<p>obj.age=${obj.age}</p>`); // -> 20
アプリの確認
See the Pen Chapter7 by Naoto Mukai (@nmukai) on CodePen.
課題
入力した文字列を逆さまにするReverseRobotクラスを,Robotクラスを継承して作成してください.
ReverseRobotには,reverseメソッドを定義し,対象の文字列は引数として渡してください.
billy = new ReverseRobot("billy");
billy.reverse("すぎやま"); // -> "まやぎす"
課題を完成させたら,Penの ZIPファイル と リンク を提出してください. 提出方法は初回のWebアプリの開発を参考にしてください.








