SEの部屋

クラスの継承について

クラスの継承とは

クラスの継承とは、既存のクラスを基にして新しいクラスを作成することです。継承元のクラスは親クラスやスーパークラス、継承先のクラスは子クラスやサブクラスと呼ばれます。子クラスは、親クラスのプロパティやメソッドを引き継ぐことができます。これにより、同じような機能を持つ複数のクラスを作成する場合に、コードの再利用性を高めることができます。
クラスの継承は、オブジェクト指向プログラミングの中心的な概念であり、多くのプログラミング言語でサポートされています。例えば、JavaやC#などの静的型付け言語では、クラスの継承が重要な機能として位置づけられています。
クラスの継承によって、子クラスは継承元のクラスのプロパティやメソッドを使用できるだけでなく、それらを拡張したり、上書きしたりすることもできます。これによって、より特化したクラスを作成することができます。また、抽象クラスやインターフェースを使用することで、継承先のクラスで必ず実装しなければならないメソッドを定義することもできます。

親クラス(スーパークラス)とは

TypeScriptのクラスでは、継承元のクラスを親クラス、基底クラス、スーパークラスと呼びます。親クラスは、子クラスに対して、メソッドやプロパティを提供するために使用されます。
親クラスは、通常は抽象化された概念を表すような一般的な実装を提供します。つまり、親クラスは、子クラスが実装すべき機能の中核となるものを提供し、子クラスはその一般的な機能を拡張して、特定の目的のための機能を実装します。
TypeScriptでは、親クラスを定義するには、クラス宣言の前にclassキーワードを使い、その後にクラス名を書きます。次に、波かっこ {} 内に親クラスのプロパティやメソッドを定義します。
例えば、以下のようにPersonクラスを作成し、その中にnameとageというプロパティを定義し、greetメソッドを定義することができます。

class Person {
  name: string;
  age: number;

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

  greet() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
  }
}

この親クラスPersonを継承して、子クラスStudentを作成することができます。その場合、Studentクラスには、親クラスPersonのプロパティやメソッドが自動的に継承されます。そして、子クラスに必要な新しいプロパティやメソッドを追加することができます。

小クラス(サブクラス)とは

子クラスは、親クラスから継承されたメソッドやプロパティを持っているだけでなく、それらを拡張したり、上書きしたりすることができます。これによって、親クラスの機能をより特化したクラスを作成することができます。
TypeScriptでは、子クラスを定義するには、クラス宣言の前にclassキーワードを使い、その後にクラス名を書きます。次に、extendsキーワードを使って親クラスを指定し、波かっこ {} 内に子クラスのプロパティやメソッドを定義します。
例えば、以下のようにPersonクラスを親クラスとして、Studentクラスを作成することができます。

class Person {
  name: string;
  age: number;

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

  greet() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
  }
}

class Student extends Person {
  studentId: number;

  constructor(name: string, age: number, studentId: number) {
    super(name, age);
    this.studentId = studentId;
  }

  study() {
    console.log(`I'm studying with student ID ${this.studentId}.`);
  }
}

この例では、StudentクラスはPersonクラスを継承しており、Personクラスのnameとageプロパティ、greetメソッドを持っています。また、Studentクラスには、新たにstudentIdプロパティが追加されています。そして、Studentクラスにはstudyメソッドが定義されています。

子クラスで親クラスのメソッドを上書きする場合は、superキーワードを使用して親クラスのメソッドを呼び出すことができます。また、抽象クラスやインターフェースを使用して、継承先のクラスで必ず実装しなければならないメソッドを定義することもできます。

オーバーライドについて

TypeScriptのクラスにおいて、子クラスで親クラスのメソッドを再定義することをオーバーライドといいます。オーバーライドによって、子クラスで親クラスのメソッドの振る舞いを変更することができます。

オーバーライドで親クラスのメソッドの書き換え

オーバーライドとは、子クラスで親クラスの同じ名前のメソッドを再定義することです。これにより、再定義されたメソッドは、親クラスのメソッドを完全に上書きします。つまり、子クラスのインスタンスからそのメソッドが呼び出された場合、親クラスのメソッドではなく、子クラスのメソッドが実行されます。
オーバーライドは、多態性の実現に不可欠です。多態性とは、同じ名前のメソッドが複数のクラスで実装されていることを指します。オーバーライドにより、子クラスは自分自身のメソッドを実行することができます。これにより、プログラムの柔軟性が向上し、コードの再利用性が高まります。
また、オーバーライドは、クラスの階層構造を理解する上で重要です。子クラスで親クラスのメソッドを再定義することで、子クラスは親クラスの機能を拡張することができます。これにより、クラスの階層構造がより明確になり、コードの保守性が向上します。
例えば、以下のような親クラスPersonとその子クラスEmployeeを考えます。

class Person {
  name: string;
  age: number;

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

  introduce() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
  }
}

class Employee extends Person {
  jobTitle: string;

  constructor(name: string, age: number, jobTitle: string) {
    super(name, age);
    this.jobTitle = jobTitle;
  }

  introduce() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old. I work as a ${this.jobTitle}.`);
  }
}

この例では、Personクラスにはintroduceメソッドが定義されています。そして、EmployeeクラスはPersonクラスを継承していて、Employeeクラスにもintroduceメソッドが定義されています。つまり、Employeeクラスは、親クラスのメソッドを引き継ぐことができます。
ただ、Employeeクラスのintroduceメソッドは、親クラスのintroduceメソッドとは異なり、従業員の職種を紹介するようになっています。このため、Employeeクラスのインスタンスからintroduceメソッドを呼び出すと、Employeeクラスのintroduceメソッドが実行され、親クラスのintroduceメソッドは実行されません。
そのため、オーバーライドは、クラスの機能を拡張し、より特定の用途に適したクラスを作成することができる強力な機能です。ただし、オーバーライドを過剰に使用すると、コードの複雑さを増す可能性があるため、適切に使用する必要があります。
また、オーバーライドを使用する場合は、コードの可読性を高めるために、コメントを追加することも重要です。コメントを追加することで、他の開発者がコードを理解しやすくなり、コードのメンテナンスや更新作業がスムーズになります。