Profile Icon

『プログラミングTypeScript』 第四章 - final 修飾子のエミュレート

プログラミングTypeScript』の第五章では、Java などのプログラミング言語における final キーワードを TypeScript で実現するアイディアについて紹介されている。面白いと思った。

Java の final は色々なところに書けるが、ここではクラスに対する final について考える。クラスに対して final をつけると、そのクラスは継承できなくなる。

TypeScript で継承不可能なクラスを定義するにはどうすれば良いだろう? コンストラクタを private にすれば継承は不可能になる

class Mammal {
  private constructor() {}
}

class Dog extends Mammal {}

const dog = new Dog()

このとき class Dog extends Mammal {} に対するエラーメッセージは Cannot extend a class 'Mammal'. Class constructor is marked as private.(2675) である。また const dog = new Dog() については Constructor of class 'Mammal' is private and only accessible within the class declaration.(2673) と言われる。エラーメッセージがすべてを言い表している。

ところで Java の final は継承を禁止するだけで final のついたクラスのインスタンス化を禁止するものではない。この修飾子をエミュレートするのであれば const dog = new Dog() 相当のものは許したい。private なコンストラクタを外から呼べない、という制約があるので Mammal クラスの中でインスタンスを作れば良いだろう。具体的には次のようにする

class Mammal {
  private constructor() {}
  static create() {
    return new Mammal()
  }
}

const mammal = Mammal.create()

これで Mammal は継承不可であり、そのインスタンスは Mammal.create() によって得られるようになった。