TypeScriptで継承(extends)とスーパークラスをわかりやすく解説!初心者向けオブジェクト指向入門
生徒
「TypeScriptでクラスを作ったんですが、似たようなコードを何度も書かないといけなくて大変です。もっと楽にできる方法はありますか?」
先生
「そんなときに便利なのが『継承(けいしょう)』です。すでにあるクラスをもとにして、新しいクラスを作ることができますよ。」
生徒
「継承ってどういう意味ですか?難しそうです…。」
先生
「難しくありませんよ。例えば、動物という大きなくくりを親クラスにして、その子どもとして犬や猫のクラスを作るイメージです。共通する部分は親に書いて、それぞれの特徴だけを子どもに追加できます。」
1. 継承(extends)とは?
TypeScriptにおける継承とは、あるクラスをもとにして新しいクラスを作る仕組みです。プログラミングでは、同じような処理を繰り返し書くとコードが長くなり、管理が難しくなってしまいます。そこで継承を使うことで、共通の機能を親クラス(スーパークラス)にまとめ、子クラス(サブクラス)に引き継ぐことができます。
継承を行うにはextendsというキーワードを使います。これにより、親クラスの性質を子クラスがそのまま利用できるようになります。
2. スーパークラスとサブクラスの関係
スーパークラスとは、親となるクラスのことです。そして、サブクラスとは、その親クラスをもとに新しく作られる子クラスのことです。
例えば「動物」という大きなクラスを作り、その中に「鳴く」「歩く」といった共通のメソッドを用意します。そして「犬」や「猫」といったサブクラスでは、それぞれの特徴を追加するだけで済みます。
3. 基本的な継承の書き方
まずは基本的なサンプルコードを見てみましょう。
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
speak() {
console.log(this.name + "が鳴きました");
}
}
class Dog extends Animal {
bark() {
console.log(this.name + "がワンワンと鳴きました");
}
}
let dog = new Dog("ポチ");
dog.speak(); // 親クラスのメソッド
dog.bark(); // 子クラスのメソッド
ポチが鳴きました
ポチがワンワンと鳴きました
この例では、Animalがスーパークラス、Dogがサブクラスです。子クラスのDogは、親クラスAnimalのspeak()をそのまま使える上に、新しくbark()を追加しています。
4. superキーワードを使って親クラスを呼び出す
サブクラスのコンストラクタ(初期化処理)では、必ずsuper()を使って親クラスのコンストラクタを呼び出す必要があります。これにより、親で定義された変数や処理を正しく引き継ぐことができます。
class Cat extends Animal {
constructor(name: string) {
super(name); // 親クラスのコンストラクタを呼び出す
}
meow() {
console.log(this.name + "がニャーと鳴きました");
}
}
let cat = new Cat("タマ");
cat.speak();
cat.meow();
タマが鳴きました
タマがニャーと鳴きました
ここでのsuper(name)は、親のAnimalクラスにあるconstructorを呼び出して、nameを正しく初期化しています。
5. メソッドの上書き(オーバーライド)
サブクラスでは、親クラスで定義されているメソッドを自分用に書き換えることもできます。これをオーバーライドと呼びます。
class Bird extends Animal {
speak() {
console.log(this.name + "がチュンチュンと鳴きました");
}
}
let bird = new Bird("ピヨ");
bird.speak();
ピヨがチュンチュンと鳴きました
このようにすると、親クラスのspeak()をそのまま使うのではなく、鳥専用の鳴き方を表現できるようになります。
6. 継承を使うメリット
継承を使うと以下のようなメリットがあります。
- 同じコードを何度も書かずに済む(コードの再利用)
- 親クラスを修正すれば、子クラスにも自動的に反映される(保守が楽になる)
- 共通の仕組みと個別の特徴をきれいに分けられる(見やすい設計)
特に初心者のうちは「似た処理は親クラスにまとめる」「特徴だけ子クラスに書く」と覚えておくと理解しやすいです。
まとめ
TypeScriptで学んできた継承やスーパークラスの仕組みは、オブジェクト指向の基本としてとても重要な概念です。特に、ひとつの親クラスから複数の子クラスへ共通の機能を引き継ぐ構造は、複雑なプログラムでも整理された形で扱える大きな利点があります。記事の中で登場した「動物」「犬」「猫」「鳥」などの例は、初心者にも理解しやすく、具体的にイメージしながら学べる代表的なモデルです。継承の考え方を使うことで、同じ性質を共有しつつ、独自の動作を追加できる柔軟な仕組みを作ることができます。
このような継承の特徴は、開発を効率化し、保守性を高めるうえでも欠かせません。親クラスで共通処理を定義し、子クラスではそれぞれの役割に応じたメソッドを追加することで、ソースコード全体が読みやすくまとまり、変更にも強くなります。さらに、super()を活用すると、親クラスに定義された処理を正しく受け取りつつ、子クラスは自身の初期化や固有機能に専念できます。こうした動作は実際の開発でも非常に多く使われるため、ここで理解しておくことが後の学習にも大きな助けになります。
また、オーバーライドの仕組みを使うことで、共通の名前を持つメソッドでも、子クラスごとに違う振る舞いを持たせることができます。動物がそれぞれ違った鳴き方をするように、ひとつの設計をもとに個別の動作を付け加えることができるのが継承の魅力です。こうした柔軟さは、ゲーム、業務システム、Webアプリケーションなど、あらゆるソフトウェア開発で役立つものです。特にTypeScriptでは、型と組み合わせることで実行前にエラーが分かりやすくなるため、オブジェクト指向の構造をより安全に運用できます。
以下では、記事で学んだ知識を踏まえた応用例として、複数のクラスを継承でつなげたサンプルコードを掲載しています。実際に動作を確認しながら読むことで、継承の仕組みやsuperの動作がより自然に理解できるようになります。
■ 継承を活用した応用サンプルコード
下記は、動物をベースに複数の特徴を持つクラスを拡張していく例です。親クラスを中心に、子クラスがどのように機能を追加していくのか確認できます。
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
speak() {
console.log(`${this.name}が何かを訴えています`);
}
}
class Dog extends Animal {
bark() {
console.log(this.name + "がワンワンと鳴きました");
}
}
class Cat extends Animal {
constructor(name: string) {
super(name);
}
meow() {
console.log(this.name + "がニャーと鳴きました");
}
}
class Bird extends Animal {
speak() {
console.log(this.name + "がチュンチュンと鳴きました");
}
}
const animals: Animal[] = [
new Dog("ポチ"),
new Cat("タマ"),
new Bird("ピヨ")
];
animals.forEach(a => a.speak());
このコードでは、Animalが全ての基本となるスーパークラスとして動作しています。Dog、Cat、Birdなどのサブクラスは、それぞれが異なる特徴を持ちながらも基本のspeak()を参照できる構造になっています。特に、鳥のように独自の鳴き方を表現したい場合には、メソッドの上書きを行い、専用の機能として振る舞いを変更しています。こうした仕組みは、実際の開発の中で複雑なオブジェクトを扱う際にも有効で、階層的に整理された構造は読みやすく、後から修正が必要な場合でも変更点が明確になります。
継承を正しく理解することで、クラスの設計意図がよく見えるようになり、今後の開発や学習においても活かせる考え方が身につきます。特に、共通部分をどこまで親クラスにまとめるか、どの動作を子クラスにだけ持たせるかを意識することで、設計の質が大きく変わります。こうした意識は、オブジェクト指向の本質でもあり、自分自身のプログラムをより整理された形に導いてくれます。
生徒
「今日の内容で継承の仕組みがだいぶ理解できました!子クラスが親クラスの機能をそのまま使えるのは便利ですね。」
先生
「そうですね。共通部分は親にまとめて、特徴だけを子に持たせるとコードがすっきりしますよ。」
生徒
「superの使い方も分かりやすかったです。親クラスの初期化を引き継げるってすごく大事なんですね。」
先生
「その通りです。継承を使うときは、親のコンストラクタを呼ぶことが基本になりますからね。」
生徒
「オーバーライドも実際の開発でたくさん使いそうです!同じ名前なのに動作を変えられるのは面白いですね。」
先生
「実際の場面でもよくありますよ。継承を使いこなせるようになると、クラス設計がもっと楽しくなります。」