自分用のメモ。
- interface:オブジェクト、クラス、関数の型のみを宣言する
- type:どんな型でも宣言する
- extends:継承する
- implements:実装する
interfaceとtypeはすごく似てるので正直どちらを使っても良いっぽいです。
extends
例えば、冒険者(Adventurer)というclassがあるとします。
class Adventurer{
name:string
hp:number
}
冒険者は名前とHPを持っています。
冒険者は別の職業にジョブチェンジできます。
ここでは冒険者→魔法使い(Wizard)にジョブチェンジするものとするとして、Wizardクラスを作るとすると以下のようになります。
//WizardクラスはAdventurerを継承しているのでhpとnameプロパティも持っている
class Wizard extends Adventurer {
mp: number
}
このとき使うのがextends。
extendsを使うと冒険者のプロパティをすべて継承する- つまり冒険者⊂魔法使いみたいな関係になる
new演算子を使って、実体化(インタンス化)します。
//ハリーポッターを作る const HarryPotter = new Wizard();
interface
interfaceは、オブジェクト・関数・クラスの構造を決めるためのもの。
要するに「このオブジェクトはこういう構造だぜ!」を決めるためのもの。
例えば、以下のような「空を飛べるよ!」なinterfaceを作ります。
interface flyable {
icanfly(): void
}
このinterfaceを実装されたクラスは空を飛べるようになります。
例えば、以下のようにWizardクラスにflyableを実装します。
class Wizard extends Adventurer implements flyable {
mp: number
icanfly(){
console.log("空を飛ぶよ!")
}
}
このようにinterfaceを実装するには、implementsを使います。
ところで「構造を決めるためのもの」と言いつつ、関数を1つしか実装していないじゃないか!と思うかもですが、それは説明しやすくするためでございます。。
extends
extendsを使うとinterfaceからinterfaceへ継承できます。
例えば「瞬間移動できるよ!」なinterfaceを作りたいとします。
ただし「瞬間移動」のスキルを身につけるには、「空を飛ぶ」スキルを先に身につけておかないといけないとしましょう。瞬間移動は空を飛ぶスキルの上位互換なのです。
そうすると、以下のように継承できます。
//空を飛べるよ!なinterface
interface flyable {
icanfly(): void;
}
//瞬間移動できるよ!なinterface
interface teleportable extends flyable {
icanteleport(): void;
}
このとき、teleportableなinterfaceを実装されたWizardクラスは、
- icanfly()
- icanteleport()
の両方のスキルを持つ必要があります。
class Wizard extends Adventurer implements teleportable {
mp: number;
icanfly() {
console.log("空を飛ぶよ!");
}
icanteleport() {
console.log("瞬間移動するよ!");
}
}
type
typeの正式名称は「Type Aliases」。
要するに「あだ名をつけるぜ!」な機能。
例えば、以下のような「空を飛べるぜ!」なtypeを作ります。
type flyable= {
icanfly(): void
}
このtypeを実装されたクラスは空を飛べるようになります。
例えば、以下のようにWizardクラスにflyableを実装します。
class Wizard extends Adventurer implements flyable {
mp: number
icanfly(){
console.log("空を飛ぶよ!")
}
}
interfaceとtypeの違い
「あれ?interfaceと同じじゃね?」と思うかもですが、大体そのとおりです
ですが厳密にいうと
typeは宣言のときに=が必要だけど、interfaceは不要typeはextendsで継承できないが、交差型と呼ばれる機能で似たようなことができる- 同名の
typeを宣言するとエラーになるが、同名のinterfaceを宣言するとマージされる typeはプリミティブ、配列、タプルなども宣言可能だけど、interfaceはオブジェクトと関数のみ宣言可能
という感じで色々違うみたいです。このページでは詳しく説明しないので別のサイトでお調べください。
implements
例えば、冒険者というジョブを持つ人が存在しない場合、冒険者はinterfaceやtypeとして作っておき、「魔法使いなどの他の職業は冒険者を実装する」みたいな形にもできます。
interface Adventurer {
name: string;
hp: number;
}
class Wizard implements Adventurer {
name: string;
hp: number;
mp: number;
}
まとめ
classにimplementsできるのは・・・
→class、type、interfaceclassにextendsできるのは・・・
→classのみ
typeにimplementsできるのは・・・
→class、type、interfacetypeにextendsできるのは・・・
→なし
interfaceにimplementsできるのは・・・
→class、type、interfaceinterfaceにextendsできるのは・・・
→interface、type
「typeをinterfaceにextendsできる」というのが個人的なハマりポイントでした。
おわり
コメント