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アプリの開発を参考にしてください.