抽象クラスは、基本的な機能を部分的に実装し、サブクラスがそれを継承して使うことを意図したクラスだ。一方、インターフェイスはクラスが「何ができるか」という契約を定義し、その機能は具体的に実装されない。
抽象クラスは、基本的なメソッドを持ちつつ、一部のメソッドはサブクラスで実装することを強制する。
// 抽象クラスとしてAnimalを定義
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
throw new Error("このメソッドはサブクラスで実装される必要があります");
}
move() {
console.log(this.name + " is moving");
}
}
// サブクラスが抽象メソッドを実装する
class Dog extends Animal {
makeSound() {
console.log("ワンワン!");
}
}
const myDog = new Dog("ポチ");
myDog.makeSound(); // 結果: ワンワン!
myDog.move(); // 結果: ポチ is moving
JavaScriptにはインターフェイスは存在しないが、オブジェクトの構造やメソッドの契約を守るような設計ができる。以下の例では、canFlyの機能を持つクラスに「飛べる」という役割を与える。
// インターフェイスのように使う関数(Mixinパターン)
const canFly = {
fly() {
console.log(this.name + " is flying!");
}
};
class Bird {
constructor(name) {
this.name = name;
}
}
// BirdクラスにcanFly機能を追加
Object.assign(Bird.prototype, canFly);
const sparrow = new Bird("スズメ");
sparrow.fly(); // 結果: スズメ is flying!