抽象クラス (abstract class)
JavaやPHPなどの言語では、abstract
修飾子を使って抽象クラスを定義できます。抽象クラスは、直接インスタンスを作れないクラスのことです。JavaScriptには抽象クラスを定義する構文はありません。一方、TypeScriptにはabstract
修飾子があり抽象クラスを表現できます。
abstract
は抽象クラスを作成する時に宣言します。抽象クラスとは直接インスタンス化(new
)することができず、必ずスーパークラスとして利用することを保証するものです。抽象クラス内のメソッドにもabstract
宣言を行うことができます。interface
と同じようにサブクラスは抽象メソッドを実装する必要があります。
Food
クラスに抽象クラスに変更し、"要冷蔵"メソッドkeepRefrigerated()
を抽象メソッドとして追加するとMeat
クラスでエラーが発生します。これはMeat
クラスにkeepRefrigerated
メソッドが実装されていないからです。
ts
abstract classFood {constructor(protectedname : string, protectedcalorie : number) {}showDebug () {console .log (`name = ${this.name } `);console .log (`calorie = ${this.calorie }kcal `);}abstractkeepRefrigerated (): boolean;}classNon-abstract class 'Meat' does not implement inherited abstract member 'keepRefrigerated' from class 'Food'.2515Non-abstract class 'Meat' does not implement inherited abstract member 'keepRefrigerated' from class 'Food'.extends Meat Food {}
ts
abstract classFood {constructor(protectedname : string, protectedcalorie : number) {}showDebug () {console .log (`name = ${this.name } `);console .log (`calorie = ${this.calorie }kcal `);}abstractkeepRefrigerated (): boolean;}classNon-abstract class 'Meat' does not implement inherited abstract member 'keepRefrigerated' from class 'Food'.2515Non-abstract class 'Meat' does not implement inherited abstract member 'keepRefrigerated' from class 'Food'.extends Meat Food {}
keepRefrigerated()
メソッドを実装することによりエラーはなくなります。
ts
classMeat extendsFood {keepRefrigerated (): boolean {return true;}}
ts
classMeat extendsFood {keepRefrigerated (): boolean {return true;}}
JavaScriptへのコンパイルしたときに起こること
TypeScriptの抽象クラスは、JavaScriptにコンパイルしたとき、消されることなく残ります。何も中身がない抽象クラスを定義してコンパイルしてみるとどうなるでしょうか。
ts
abstract classAbstractClass {}
ts
abstract classAbstractClass {}
上のTypeScriptをコンパイルすると、次のJavaScriptが生成されます。
コンパイル結果ts
class AbstractClass {}
コンパイル結果ts
class AbstractClass {}
このように、抽象クラスはabstract
修飾子が外され、ただのクラスとしてコンパイルされます。
抽象メソッドは、コンパイル時に消されます。たとえば、次の実装の中身があるconcreteMethod
は残りますが、抽象メソッドのabstractMethod
は消えます。
ts
abstract classAbstractClass {concreteMethod (): void {/* 実装の中身 */}abstractabstractMethod (): void;}
ts
abstract classAbstractClass {concreteMethod (): void {/* 実装の中身 */}abstractabstractMethod (): void;}
上のTypeScriptのコンパイル結果は次のようになります。
コンパイル結果ts
class AbstractClass {concreteMethod() {/* 実装の中身 */}}
コンパイル結果ts
class AbstractClass {concreteMethod() {/* 実装の中身 */}}