JavaScript⑤・オブジェクト指向

Image from Gyazo

オブジェクト指向

JavaScriptはオブジェクト指向言語ですが,ES6以前は クラス という概念が存在せず, プロトタイプ と呼ばれる概念が用いられてきました. ES6では,クラス の概念が導入されるなど,オブジェクト指向の機能が大幅に改良され, JavaやC#などの他のプログラミング言語と同様なオブジェクト指向の実装が可能になりました. ここでは,ES6のオブジェクト指向に注目して解説します.

CodePenの準備

CodePenにアクセスして,Penを作成し,タイトルを設定しましょう. Penのタイトルは「Chapter7」に設定しましょう.

https://codepen.io/

Image from Gyazo

クラスの定義

オブジェクト指向は,その名が示しているように, 「もの(オブジェクト)」を基準として実装する考え方です. 一般に,オブジェクトの型となるのが,クラス とみなすことができます. ここでは,会話可能な Robot クラスを定義することを考えましょう.

クラスには,プロパティメソッドを定義します. プロパティは,クラスに紐付けられた「変数」, メソッドは,クラスに紐付けられた「関数」のことを指します (正確にはクラスを実体化したインスタンスに紐付けられます).

Robotクラスには,nameプロパティ,constructorメソッド,helloメソッドを定義しています. このうち,constructorは特殊なメソッドで,newを用いてRobotクラスの実体を作成するときに実行されます. 作成された実体のことを インスタンス と呼びます.

Image from Gyazo

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>`);

Image from Gyazo

インスタンスに紐付けられているメソッドにもドット記法でアクセスします. ここでは,robin.hello()で表します.

// helloメソッド
robin.hello();

Image from Gyazo

クラスの継承

オブジェクト指向では,クラスを 継承 することで,既存のクラスを効率良く再利用することが可能です. ここでは, じゃんけん(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();

Image from Gyazo

オブジェクト・リテラル

オブジェクト・リテラルで定義

クラスと同様の機能を オブジェクト・リテラル でも実現可能です. オブジェクト・リテラルでは,プロパティをプロパティ名:値, また,メソッドをメソッド名(){}として定義します. ここでは,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();

Image from Gyazo

JSONへの変換

インスタンスやオブジェクトに紐付けられたプロパティは, JSON.stringify()でJSON(JavaScript Object Notation)に変換可能です. JSONでは全てのデータが文字列として表現されます. ただし,メソッドはJSONに変換できないので注意が必要です. ここでは,nameプロパティとageプロパティがJSONに変換されていることが確認できます.

// オブジェクトからJSON文字列に変換
let json = JSON.stringify(david);
document.write(`<p>json=${json}</p>`);

Image from Gyazo

逆に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

Image from Gyazo

アプリの確認

See the Pen Chapter7 by Naoto Mukai (@nmukai) on CodePen.

課題

入力した文字列を逆さまにするReverseRobotクラスを,Robotクラスを継承して作成してください. ReverseRobotには,reverseメソッドを定義し,対象の文字列は引数として渡してください.

billy = new ReverseRobot("billy");
billy.reverse("すぎやま"); // -> "まやぎす"

課題を完成させたら,Penの ZIPファイルリンク を提出してください. 提出方法は初回のWebアプリの開発を参考にしてください.

参考書籍

愛知県名古屋市にある椙山女学園大学 文化情報学部 向研究室の公式サイトです. 専門は情報科学であり,人工知能やデータベースなどの技術要素を指導しています. この公式サイトでは,授業で使用している教材を公開すると共に, ベールに包まれた女子大教員のミステリアスな日常を4コマ漫画でお伝えしていきます. サイトに関するご意見やご質問はFacebookまたはTwitterでお問い合わせください.