クラスに型をつける

INPUT · スライド

interface を実装する

01 / 05

この形を満たします、と宣言する

章2で書いた interface は、形に名前をつけるものだった。クラスの名前のうしろに implements と書くと、「このクラスはその形を満たします」という宣言になるよ。

interface の中では、メソッドは naku(): string; のように名前と形だけを書く。中身は書かない。中身を書くのはクラスの仕事だからだ。

あとは class Inu implements Doubutsu と宣言して、約束したものをクラスの中にそろえるだけ。

interface Doubutsu {  naku(): string;}class Inu implements Doubutsu {  naku(): string {    return "わん";  }}console.log(new Inu().naku());

実行結果

わん

02 / 05

フィールドも約束できる

interface に書けるのはメソッドだけじゃない。持っていてほしいフィールドも並べられる。

クラス側は、宣言して constructor で入れる。ここは前のレッスンまでとまったく同じだよ。

interface Doubutsu {  namae: string;  naku(): string;}class Neko implements Doubutsu {  namae: string;  constructor(namae: string) {    this.namae = namae;  }  naku(): string {    return this.namae + "がにゃー";  }}console.log(new Neko("たま").naku());

実行結果

たまがにゃー

03 / 05

書き忘れるとクラス側で止まる

naku を書き忘れたまま implements Doubutsu と宣言すると、クラスを書いたところでエラーになる。

「クラス 'Inu' はインターフェイス 'Doubutsu' を正しく実装していません」「プロパティ 'naku' は型 'Inu' にありませんが、型 'Doubutsu' では必須です」。あとで書こうと思って忘れたまま動いてしまう、という事故がなくなるよ。

interface Doubutsu {  namae: string;  naku(): string;}class Inu implements Doubutsu {  namae: string;  constructor(namae: string) {    this.namae = namae;  }}

実行結果

型のエラー: クラス 'Inu' はインターフェイス 'Doubutsu' を正しく実装していません。
  プロパティ 'naku' は型 'Inu' にありませんが、型 'Doubutsu' では必須です。

04 / 05

同じ約束をしたクラスは並べられる

同じ interface を、いくつのクラスが実装してもいい。約束が同じなので、まとめて同じ配列に入れて同じように扱えるよ。

配列の型を Doubutsu[] と書けば、中身が Inu でも Neko でも naku() が呼べることは保証されている。

interface Doubutsu {  naku(): string;}class Inu implements Doubutsu {  naku(): string {    return "わん";  }}class Neko implements Doubutsu {  naku(): string {    return "にゃー";  }}const list: Doubutsu[] = [new Inu(), new Neko()];for (const d of list) {  console.log(d.naku());}

実行結果

わん
にゃー

05 / 05

extends とのちがい

似ているけれど役目がちがうよ。

  • extends … 親の中身をもらう(書かなくても動く)
  • implements … 形を約束するだけ(中身は自分で書く)

implements はもらえるものが何もない。そのかわり、書き忘れたら必ず気づける。共通の中身があるなら extends、形だけそろえたいなら implements だ。ここから書いてみよう。