TypeScriptでは、オブジェクト指向プログラミング(OOP)の概念を利用して、クラスを使ったプログラム開発が可能です。クラスや継承、アクセス修飾子など、TypeScriptのOOPの基礎を学んでいきましょう。
クラスの定義
クラスはオブジェクトの設計図として機能し、データ(プロパティ)と振る舞い(メソッド)をまとめることができます。TypeScriptでクラスを定義する基本的な方法を見てみましょう。
typescript
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): void {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
let person = new Person("Alice", 30);
person.greet(); // Hello, my name is Alice and I am 30 years old.
上記の例では、Person
クラスを定義し、name
とage
というプロパティを持たせています。constructor
はクラスのインスタンスを生成するときに呼び出される特別なメソッドで、プロパティの初期化を行います。
継承とポリモーフィズム
TypeScriptではクラスの継承を使って、既存のクラスをベースに新しいクラスを作成することができます。継承を使うことでコードの再利用性が向上し、共通の機能を親クラスにまとめることができます。
typescript
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log("Some generic sound...");
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log("Woof! Woof!");
}
}
let genericAnimal = new Animal("Generic Animal");
genericAnimal.makeSound(); // Some generic sound...
let dog = new Dog("Buddy");
dog.makeSound(); // Woof! Woof!
この例では、Animal
クラスを親クラスとしてDog
クラスが継承しています。Dog
クラスはmakeSound
メソッドをオーバーライドして独自の実装を提供しています。これにより、ポリモーフィズム(多態性)を実現し、同じメソッド名で異なる動作を持たせることができます。
アクセス修飾子(public, private, protected)
TypeScriptでは、クラスのプロパティやメソッドにアクセス修飾子を使って可視性を制御できます。アクセス修飾子には以下の3種類があります。
public(デフォルト)
- クラス外部からアクセス可能です。明示的に
public
と指定しなくても、すべてのプロパティやメソッドはデフォルトでpublic
になります。
typescriptclass Car { public model: string; constructor(model: string) { this.model = model; } } let car = new Car("Toyota"); console.log(car.model); // Toyota
- クラス外部からアクセス可能です。明示的に
private
- クラス内部でのみアクセス可能です。クラス外部から直接アクセスすることはできません。
typescriptclass BankAccount { private balance: number; constructor(initialBalance: number) { this.balance = initialBalance; } deposit(amount: number): void { this.balance += amount; } getBalance(): number { return this.balance; } } let account = new BankAccount(1000); account.deposit(500); console.log(account.getBalance()); // 1500 // console.log(account.balance); // エラー: 'balance' は private です
protected
- クラス内部およびサブクラスからアクセス可能です。サブクラスでは直接アクセスできますが、クラス外部からはアクセスできません。
typescriptclass Employee { protected role: string; constructor(role: string) { this.role = role; } } class Manager extends Employee { constructor() { super("Manager"); } getRole(): string { return this.role; } } let manager = new Manager(); console.log(manager.getRole()); // Manager // console.log(manager.role); // エラー: 'role' は protected です
抽象クラスとインターフェースの比較
TypeScriptでは、抽象クラスとインターフェースを使ってクラスの構造を定義することができます。どちらも共通のインターフェースを提供することが目的ですが、使用する場面が異なります。
抽象クラス
- 抽象クラスはインスタンス化できないクラスで、他のクラスによって継承されるために使われます。
- 抽象クラスは具体的なメソッドの実装を持つことができ、抽象メソッドを定義することで、サブクラスに実装を強制することができます。
typescript
abstract class Vehicle {
abstract move(): void;
start(): void {
console.log("Starting vehicle...");
}
}
class Car extends Vehicle {
move(): void {
console.log("The car is moving.");
}
}
let car = new Car();
car.start(); // Starting vehicle...
car.move(); // The car is moving.
インターフェース
- インターフェースはプロパティやメソッドの定義のみを持ち、実装を持ちません。
- クラスは複数のインターフェースを実装することができますが、抽象クラスは単一のクラスしか継承できません。
typescript
interface Flyable {
fly(): void;
}
interface Swimmable {
swim(): void;
}
class SuperHero implements Flyable, Swimmable {
fly(): void {
console.log("Flying high!");
}
swim(): void {
console.log("Swimming fast!");
}
}
let hero = new SuperHero();
hero.fly(); // Flying high!
hero.swim(); // Swimming fast!
抽象クラスは基本的な機能を持つクラスをベースにサブクラスを作りたい場合に有効です。一方、インターフェースはクラスに特定の機能を付与する際に使用します。クラスの多重継承ができないTypeScriptでは、インターフェースを用いることで柔軟に機能を組み合わせることが可能です。
まとめ
TypeScriptでは、クラスやオブジェクト指向プログラミングの概念を使うことで、複雑なアプリケーションの設計が可能です。クラスの定義や継承、アクセス修飾子を理解することで、コードの再利用性と安全性を高めることができます。また、抽象クラスとインターフェースの違いを理解し、適切に使い分けることで、より柔軟で拡張性のあるコードを書くことができます。