TypeScript - 抽象クラス

こんにちは、将来のプログラマーたち!今日は、TypeScriptの世界に足を踏み入れ、その強力な機能の一つである抽象クラスを探求する興味深い旅に出かけましょう。プログラミングが初めてであっても心配しないでください。私はこの概念をステップバイステップでガイドし、これまでに数多くの学生を指導してきました。それでは、さあ始めましょう!

TypeScript - Abstract Classes

抽象クラスとは?

抽象クラスの詳細に踏み込む前に、簡単な類似を考えてみましょう。あなたが車のディーラーで、「Vehicle(車両)」という看板を見たとします。実際には「Vehicle(車両)」を購入することはできません。それはあまりにも一般的です。具体的な車両を選ぶ必要があります。例えば、車、トラック、またはバイクなどです。プログラミングでは、抽象クラスはその一般的な「Vehicle(車両)」的概念と同じで、他のクラスの蓝图として機能しますが、直接オブジェクトを作成することはできません。

TypeScriptの抽象クラスは、他のクラスが継承するためのベースクラスとして機能します。抽象メソッド(ボディのないメソッド)と具体メソッド(ボディがあるメソッド)を含むことができます。重要なことは、抽象クラスのインスタンスを直接作成できないということです。

抽象クラスの作成

それでは、TypeScriptで抽象クラスを作成する方法を見てみましょう。abstractキーワードをclassキーワードの前に使用します。以下は基本的な構造です:

abstract class ClassName {
// プロパティとメソッドをここに
}

抽象メソッド

抽象クラスには抽象メソッドがあります。これらは宣言されていますが、抽象クラス内では実装されていません。この抽象クラスを継承するクラスは、これらのメソッドを実装する必要があります。

具体メソッド

抽象クラスには具体メソッドも含まれることができ、これらは完全に実装されたメソッドで、子クラスによって継承されます。

例1: Shape抽象クラス

抽象クラスの動作を説明する簡単な例を作成してみましょう。抽象クラスShapeを作成し、抽象メソッドcalculateArea()を含めます。

abstract class Shape {
color: string;

constructor(color: string) {
this.color = color;
}

abstract calculateArea(): number;

displayColor(): void {
console.log(`This shape is ${this.color}`);
}
}

この例では:

  • Shapeは抽象クラスです。
  • colorはすべての形状が持つプロパティです。
  • calculateArea()は抽象メソッドで、ボディーがありません。
  • displayColor()は具体メソッドで、すべての形状がそのまま使用できます。

次に、Shapeクラスを継承する特定の形状を作成します:

class Circle extends Shape {
radius: number;

constructor(color: string, radius: number) {
super(color);
this.radius = radius;
}

calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
}

class Rectangle extends Shape {
width: number;
height: number;

constructor(color: string, width: number, height: number) {
super(color);
this.width = width;
this.height = height;
}

calculateArea(): number {
return this.width * this.height;
}
}

これらのクラスを使用します:

const circle = new Circle("red", 5);
console.log(circle.calculateArea()); // 出力: 78.53981633974483
circle.displayColor(); // 出力: This shape is red

const rectangle = new Rectangle("blue", 4, 6);
console.log(rectangle.calculateArea()); // 出力: 24
rectangle.displayColor(); // 出力: This shape is blue

この例では、CircleRectangleはどちらもShapeクラスを継承し、calculateArea()メソッドの独自の実装を提供しています。また、ShapeクラスからdisplayColor()メソッドを継承しています。

例2: Animal抽象クラス

理解を深めるために別の例を作成しましょう。今回は抽象クラスAnimalを作成します:

abstract class Animal {
name: string;

constructor(name: string) {
this.name = name;
}

abstract makeSound(): void;

move(distance: number = 0): void {
console.log(`${this.name} moved ${distance} meters.`);
}
}

class Dog extends Animal {
constructor(name: string) {
super(name);
}

makeSound(): void {
console.log("Woof! Woof!");
}
}

class Cat extends Animal {
constructor(name: string) {
super(name);
}

makeSound(): void {
console.log("Meow!");
}
}

これらのクラスを使用します:

const dog = new Dog("Buddy");
dog.makeSound(); // 出力: Woof! Woof!
dog.move(10); // 出力: Buddy moved 10 meters.

const cat = new Cat("Whiskers");
cat.makeSound(); // 出力: Meow!
cat.move(5); // 出力: Whiskers moved 5 meters.

この例では、Animalは抽象クラスで、抽象メソッドmakeSound()と具体メソッドmove()を持ちます。DogCatAnimalを継承し、makeSound()メソッドの独自の実装を提供しています。

抽象クラスの利点

おそらく、「こんな手間をかける必要があるの?普通のクラスを使わない?」と思っているかもしれません。抽象クラスは、関連するクラス群に対して共通のインターフェースを定義する場合に非常に有用です。以下のことができます:

  1. 関連するクラス群の共通構造を定義します。
  2. 子クラスが実装する必要があるメソッドを強制します。
  3. 子クラスが使用できる共通機能を提供します。

これは、他のクラスが従うテンプレートや契約を作成する方法であり、関連するクラス間で一貫性を保ちつつ、必要な場合にカスタマイズを許可する方法です。

抽象クラスのメソッド

以下の表に、抽象クラスに持てるメソッドの種類をまとめます:

メソッドタイプ 説明 抽象クラスで呼び出せる? 子クラスで実装が必要?
抽象メソッド 実装なしで宣言 いいえ はい
具体メソッド 完全に実装されたメソッド はい いいえ(オーバーライド可能)

結論

そして、ここまで、TypeScriptの抽象クラスの世界を旅しました。抽象クラスが何であるか、それをどのように作成し、実際の例でそれをどのように使用するかを理解しました。あなたはこの強力なTypeScriptの機能に対して固い基盤を築きました。

抽象クラスは、ビルディングの蓝图のように、構造といくつかの詳細を提供しますが、それを拡張するクラスが具体的な詳細を埋める的责任があります。

プログラミングの旅を続ける中で、抽象クラスは非常に有用なツールとなります。きれいで整理された、保守しやすいコードを書く助けになります。それでは、心を込めて抽象化を試み、次回までにさらなる探索と学習を続けましょう!

幸せなコーディングを、そして次回まで!

Credits: Image by storyset