typescript - 抽象クラスとインターフェース

今回は説明文が大体ルー大柴になってしまうオブジェクト指向のクラスについてです。クラスの中でも抽象クラスとインターフェースというややこしい概念が出てきたのでnoteにまとめたいと思います。前回の型アサーション同様初心者がいろいろな記事をみて理解できた範囲でお話するので、間違っていたら指摘をお願いします。
では、まず抽象クラスとインターフェースについて簡単に説明したと思います。

抽象クラス

抽象クラスは下のようにabstractを付けたクラスで1つ以上のメソッドを定義します。プロパティなどは定義しません。またメソッドの具体的な処理も記載しません。あくまでこのような名前のメソッドがあるということを明示するだけです。extendsで継承します。

abstract class Human {
   abstract say(msg: string): string;
}
class Man extends Human {
   public say(msg: string): string {
       return msg + "だぜ!";
   }
}
let takashi = new Man();
alert(takashi.say("ハロー")); //ハローだぜ!

また抽象クラスを継承したクラスは全てのメソッドを引き継ぐ必要があります。

abstract class AHuman {
   abstract man_say(msg: string): string;
   abstract woman_say(msg: string): string;
}
class Man extends AHuman {
   public man_say(msg: string): string {
       return msg + "だぜ!";
   }
   // woman_sayを継承してないのでエラー
}

どちらもplayground環境ではコンパイルエラーを返しますが、無視しても実行時エラーは出ません。

インターフェース

インターフェースは下のようにinterfaceを付け、プロパティとメソッドを定義します。抽象クラス同様、具体的な中身については記述しません。また、?を付けたプロパティは任意になります。implementsで継承します。

interface IHuman {
   name: string;
   age?: number;
   hello(msg: string): string;
}

class Shiro implements IHuman {
   constructor(public name: string) {
   }
   public hello(msg: string): string {
       return `${msg}${this.name}`;
   }
}

let shiro = new Shiro("浜田");
alert(shiro.hello("こんにちは")); //こんにちは、浜田

下のように、抽象クラス同様継承されていないメソッドがあるとエラーが出ます。このエラーはコンパイルのエラーです。

interface IHuman {
   name: string;
   age?: number;
   hello(msg: string): string;
   goodbye(msg: strign): string;
}
class Shiro implements IHuman {
   constructor(public name: string) {
   }
   public hello(msg: string): string {
       return `${msg}${this.name}`;
   }
}

何が違う?

ここまで見てきた感じでは違いはありませんが、異なる部分もあります。例えば、インターフェースには多重継承があります。下のように、あるクラスに二つのインターフェースを継承させることができます。これは抽象クラスではできません。

interface IHuman {
   name: string;
   age?: number;
   hello(msg: string): string;
}
interface Animal {
   types: string;
}
class Taro implements IHuman, Animal {
   types: string;
   constructor(public name: string, public age: number) {
       this.types = "monkey";
   }
   public hello(msg: string): string {
       return `${msg} ${this.name}です。`;
   }
}


抽象クラスは不要?

ここまでで見ると抽象クラスは不要なのでは?という考えが浮かびます。現状私も抽象クラスが必要ということに関して納得できる答えを見出せていません。しかし、私よりも頭が良くて合理主義なプログラマー達が無駄なものを作るとも思えないし、作ったとしても残しておくわけありません。ここに関してはもう少し勉強しようと思います。


この記事が気に入ったらサポートをしてみませんか?