メインコンテンツまでスキップ

抽象クラス (abstract class)

JavaやPHPなどの言語では、abstract修飾子を使って抽象クラスを定義できます。抽象クラスは、直接インスタンスを作れないクラスのことです。JavaScriptには抽象クラスを定義する構文はありません。一方、TypeScriptにはabstract修飾子があり抽象クラスを表現できます。

abstractは抽象クラスを作成する時に宣言します。抽象クラスとは直接インスタンス化(new)することができず、必ずスーパークラスとして利用することを保証するものです。抽象クラス内のメソッドにもabstract宣言を行うことができます。interfaceと同じようにサブクラスは抽象メソッドを実装する必要があります。

Foodクラスに抽象クラスに変更し、"要冷蔵"メソッドkeepRefrigerated()を抽象メソッドとして追加するとMeatクラスでエラーが発生します。これはMeatクラスにkeepRefrigeratedメソッドが実装されていないからです。

ts
abstract class Food {
constructor(protected name: string, protected calorie: number) {}
showDebug() {
console.log(`name = ${this.name} `);
console.log(`calorie = ${this.calorie}kcal `);
}
abstract keepRefrigerated(): boolean;
}
 
class Meat extends Food {}
Non-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'.
ts
abstract class Food {
constructor(protected name: string, protected calorie: number) {}
showDebug() {
console.log(`name = ${this.name} `);
console.log(`calorie = ${this.calorie}kcal `);
}
abstract keepRefrigerated(): boolean;
}
 
class Meat extends Food {}
Non-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'.

keepRefrigerated()メソッドを実装することによりエラーはなくなります。

ts
class Meat extends Food {
keepRefrigerated(): boolean {
return true;
}
}
ts
class Meat extends Food {
keepRefrigerated(): boolean {
return true;
}
}

JavaScriptへのコンパイルしたときに起こること

TypeScriptの抽象クラスは、JavaScriptにコンパイルしたとき、消されることなく残ります。何も中身がない抽象クラスを定義してコンパイルしてみるとどうなるでしょうか。

ts
abstract class AbstractClass {}
ts
abstract class AbstractClass {}

上のTypeScriptをコンパイルすると、次のJavaScriptが生成されます。

コンパイル結果
ts
class AbstractClass {
}
 
コンパイル結果
ts
class AbstractClass {
}
 

このように、抽象クラスはabstract修飾子が外され、ただのクラスとしてコンパイルされます。

抽象メソッドは、コンパイル時に消されます。たとえば、次の実装の中身があるconcreteMethodは残りますが、抽象メソッドのabstractMethodは消えます。

ts
abstract class AbstractClass {
concreteMethod(): void {
/* 実装の中身 */
}
abstract abstractMethod(): void;
}
ts
abstract class AbstractClass {
concreteMethod(): void {
/* 実装の中身 */
}
abstract abstractMethod(): void;
}

上のTypeScriptのコンパイル結果は次のようになります。

コンパイル結果
ts
class AbstractClass {
concreteMethod() {
/* 実装の中身 */
}
}
 
コンパイル結果
ts
class AbstractClass {
concreteMethod() {
/* 実装の中身 */
}
}