第12回 クラスの利用TypeScriptで学ぶJavaScript入門(6/6 ページ)

» 2015年07月16日 05時00分 公開
[羽山博]
前のページへ 1|2|3|4|5|6       

クラスの継承とメソッドのオーバーライド

 本稿の最初に、プログラミングとは「世界にあるさまざまな物事を記述すること」と述べた。クラスを使うと、単に変数を使う場合に比べて、物事を日常に近い感覚で表現できる。しかし、物事にはさまざまな関係がある。例えば、ある部品を改良して新しい部品を作ったとしよう。新しい部品を表すために別のクラスを定義し直すのは面倒である。ここで使っている猫クラスにしても、私たちが普段、目にする猫だけでなく、トラなどのネコ科の生き物を表したいことがあるはずだ。

 そのためのクラスの機能が継承である。継承とは、元のクラス(親クラス)の機能を全て受け継いだ新しいクラス(子クラス)を定義することである。もちろん、全く同じものを作るのではなく、子クラス独自のプロパティやメソッドを持たせることができる。

 継承元の親クラスのことを基底クラスと呼び、継承先の子クラスのことを派生クラスと呼ぶこともある。また、親クラスをスーパークラスと呼び、子クラスをサブクラスと呼ぶこともある。継承も、派生と呼んだり、サブクラス化と呼んだりすることがある。

 では、Catクラスを継承したTigerクラスを定義してみよう。コードを簡単にするために、Catクラスにはnameプロパティとmeowメソッドのみがあることにする。

class Cat {
  private name: string;
  public setName(s: string) {
    this.name = s.slice(0, 8);
  }
  public getName(): string {
    return this.name;
  }
  public meow(): string {
    return "にゃーん";
  }
}

class Tiger extends Cat {  // (1)
  public meow(): string// (2)
    return "がおー";
  }
}

var myTiger = new Tiger();  // (3)
myTiger.setName("とらお");  // (4)
alert("私の虎の名前は" + myTiger.getName() + "で、" + myTiger.meow() + "と鳴きます");  // (5)
window.close();


 (1)がクラスを継承した新しいクラスを定義するための記述になる。クラスを継承するには、新しいクラスの名前の後にextendsというキーワードを書き、その後に親クラスの名前を書けばよい。これで、親クラスの全ての機能が受け継がれる。一方で、(2)のように、子クラス独自のメソッドを書いてもよい。その場合、親クラスにはない新たなメソッドを書くこともできるし、ここでの例のように、親クラスのメソッドと同じ名前のメソッドにすることもできる。その場合、親クラスにある機能が、子クラスでは異なる働きをすることになる。このようにして親クラスのメソッドを子クラスで定義し直すことを、オーバーライドと呼ぶ。用語がオーバーロードと似ているが、異なるものなので注意してほしい。

 続いて、(3)ではTigerクラスのインスタンスを作成し、(4)でnameプロパティに名前を設定している。ここでは、setNameメソッドに注目しよう。TigerクラスにはsetNameメソッドは書かれていないが、Catクラスを継承しているので、CatクラスのsetNameメソッドが使えるというわけだ。同様にして、(5)で呼び出しているgetNameメソッドはCatクラスで定義されたものである。しかし、meowメソッドはTigerクラスでオーバーライドしたものが使われる。

 実行例を見ておこう。

図10 Catクラスを継承したTigerクラスを利用するプログラムの実行例 図10 Catクラスを継承したTigerクラスを利用するプログラムの実行例
setNameメソッドやgetNameメソッドはTigerクラスにはないが、親クラスにあるメソッドが使われる。一方、meowメソッドはオーバーライドしたので、子クラスのものが使われる。

[コラム] JavaScriptではどう記述されている?

 ここでは、TypeScriptのプログラムがJavaScriptのプログラムにどうコンパイルされたかをいちいち示していませんが、上のTypeScriptプログラムは、かなり複雑なJavaScriptプログラムにコンパイルされています。参考のため、画面の一部分を示しておきますが、ちょっと敬遠したくなるようなコードですね。

図11 クラスの継承をJavaScriptで表すとかなり複雑なコードになる 図11 クラスの継承をJavaScriptで表すとかなり複雑なコードになる
Catクラスを継承したTigerクラスを定義し、利用するプログラムがJavaScriptにコンパイルされた結果(画面の右側)。

 TypeScriptのクラスを使うと、さまざまな物事が簡潔に表せることが、この画面からもうかがえるでしょう。


 なお、親クラスのメソッドを呼び出したいときには、メソッド名の前にsuperを付ければよい。例えば、以下のようにmeowlikecatメソッドを作り、親クラスのmeowメソッドを呼び出すようにすれば、トラを猫なで声で鳴かせることもできる。

class Cat {
  private name: string;
  public setName(s: string) {
    this.name = s.slice(0, 8);
  }
  public getName(): string {
    return this.name;
  }
  public meow(): string {
    return "にゃーん";
  }
}

class Tiger extends Cat {
  public meow(): string {
    return "がおー";
  }
  public meowlikecat(): string {
    return super.meow();  // (1)
  }
}

var myTiger = new Tiger();
myTiger.setName("とらお");
alert("私の虎の名前は" + myTiger.getName() + "ですが、甘えているときには" + myTiger.meowlikecat() + "と鳴きます");
window.close();


 (1)でsuperというキーワードを指定し、親クラスのメソッドを呼び出していることが分かる。実行例は以下の通り。

図12 オーバーライドしたメソッドではなく、親クラスのメソッドを呼び出すプログラムの実行例 図12 オーバーライドしたメソッドではなく、親クラスのメソッドを呼び出すプログラムの実行例
TigerクラスはCatクラスを継承しており、meowメソッドをオーバーライドしている。Tigerクラスで親クラスのmeowメソッドを使いたいときには「super.meow()」と書けばよい。トラがネコっぽい声を出すこともあるだろう。

 以上で、TypeScriptのクラスについての基本は、ほぼ卒業である。プログラミングに初めて取り組む人にとって、クラスの書き方や取り扱いは難しいという先入観があるかもしれない。しかし、クラスとは、コンピューターの都合よりも、私たちの日常の感覚に近い捉え方から、物事の表現にアプローチしているものと考えられる。多少なりとも身近に感じてもらえただろうか。


 1年以上にわたる連載もとうとう最終回を迎えてしまった。Playgroundを利用するとTypeScriptのプログラムが手軽に作れるので、初めてプログラミングに取り組む人でも、一つ一つ動作を確認しながらさまざまな機能を学べたことと思う。これまでの知識を一通り身に付けていれば、本連載で紹介できなかった機能についても、言語仕様などを読み進めながら、自ら理解を深めていけるはずである。さらにプログラミングを身に付け、より実用的なプログラムにチャレンジする第一歩として、本連載のバックナンバーなども活用していただけるとありがたい。

「TypeScriptで学ぶJavaScript入門」のインデックス

TypeScriptで学ぶJavaScript入門

前のページへ 1|2|3|4|5|6       

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。