オーバーライドとは
オブジェクト指向プログラミングにおける
オーバーライド (override) とは、スーパークラス(親クラス)で定義されたメソッドを、サブクラス(子クラス)で
再定義し、その動作を上書き(変更)する機能です。これにより、継承関係にあるクラス間で、同じ名前のメソッドでありながら異なる振る舞いを実現できます。
具体例
例えば、`Base`クラスに`print`というメソッドが定義されているとします。この`Base`クラスを継承した`Derived`クラスでは、`Base`クラスの`print`メソッドをオーバーライドすることで、`Derived`クラス独自の`print`メソッドを定義できます。
この仕組みは、
オブジェクト指向プログラミングにおける
ポリモーフィズム(多態性)を実現する上で重要な役割を果たします。
オーバーライドの条件
一般的に、オーバーライドが成立するためには、以下の条件を満たす必要があります。
メソッド名が同じであること
引数の数と型が同じであること
戻り値の型が同じであること
これらの条件が満たされていない場合、オーバーライドではなく、別のメソッドとして扱われることになります。
オーバーロードとの違い
メソッドのオーバーロード (overload) は、同じクラス内で、引数の型や数が異なる同じ名前のメソッドを複数定義する機能です。オーバーライドとは異なる概念であるため、混同しないように注意が必要です。
ただし、Rubyのようにオーバーロードの概念を持たない言語もあり、そのような言語では、メソッド名が同じであれば、引数の型や数に関わらずオーバーライドが成立します。
Javaでは、インスタンスメソッドはデフォルトで仮想メソッドとして扱われ、サブクラスで自由にオーバーライドできます。
`final`キーワードを使用することで、メソッドのオーバーライドを禁止できます。
`@Override`アノテーションを使用することで、コンパイラにオーバーライドを明示的に通知できます(コンパイルエラーでミスを検出可能)。ただし、アノテーションは必須ではありません。
C#
C#でのオーバーライドには、以下のような特徴があります。
仮想メソッド(`virtual`修飾子付き)または抽象メソッドのオーバーライドには、`override`キーワードが必須です。
インターフェースのメソッドを実装する場合は、`override`キーワードは不要です。
デフォルトではメソッドは非仮想であり、`virtual`修飾子を追加することでオーバーライド可能になります。
プロパティ、インデクサ、イベントも、`virtual`修飾されていればオーバーライド可能です。
`sealed`キーワードを使用すると、オーバーライドを禁止できます。
その他の言語
KotlinやSwiftなどの比較的新しい言語では、C#と同様にオーバーライドには`override`キーワードの指定が必須です。
オーバーライド時の注意点
特に、スーパークラスの実装者とサブクラスの実装者が異なる場合、オーバーライドに関する問題が発生する可能性があります。
Javaの場合: スーパークラスに新しいメソッドを追加した際に、サブクラスに同じシグネチャのメソッドが存在すると、意図せずオーバーライドしてしまうことがあります。
オーバーライドの失敗: スーパークラスのメソッドのシグネチャ変更やtypoなどによって、オーバーライドが正しく行われないことがあります。
Javaでは`@Override`
アノテーションが推奨されていますが、必須ではありません。
C#では、メソッドがデフォルトで非仮想であり、オーバーライド時に`override`キーワードが必須であるため、このような問題は発生しにくくなっています。
まとめ
オーバーライドは、
オブジェクト指向プログラミングにおける重要な概念です。適切に利用することで、コードの柔軟性や再利用性を高めることができます。各言語の仕様をよく理解し、注意して実装することが重要です。
関連概念
オブジェクト指向プログラミング
ポリモーフィズム(多態性)
仮想メソッド
メソッドのオーバーロード