オブジェクト指向プログラミングにおいてオーバーライド (override) とは、スーパークラスで定義されたメソッドをサブクラスで定義し直し、動作を上書き(変更)することである。
例えば、あるクラスBaseにメソッドprintがあり、あるクラスDerivedがクラスBaseを継承したとする。そのとき、クラスDerivedはクラスBaseにあるメソッドprintをオーバーライドすることにより、再定義することができる。これはオブジェクト指向プログラミングにおけるポリモーフィズム(多態性)を実現する際によく使われる。
通例、オーバーライドを可能とする条件として、メソッドの名前、引数の数と型の順序、そして戻り値の型が統一されている必要がある。
メソッドのオーバーロード(多重定義、overload)と名前は似ているが、まったく異なる概念である。
Rubyのようにオーバーロードの概念がなく、引数の型や数の条件がなくメソッド名が同一なだけでオーバーライドが成立するプログラミング言語もある。
オーバーライドの例
Java
Javaのインスタンスメソッドは仮想メソッドであり、派生クラスでオーバーライド可能である。インスタンスメソッドを非仮想にする手段はないが、finalキーワードを指定することでオーバーライドを禁止することはできる。
なお、Java SE 5から導入されたアノテーション@Overrideを用いることで、メソッドがオーバーライドされていることをコンパイラに知らせることができる(正しくオーバーライドされていない場合、コンパイルエラーとなる)。しかし、アノテーションの指定はオプションであり必須ではない。
実行結果:
C#
C#のオーバーライドの特徴として、以下が挙げられる。
- 仮想メソッドおよび抽象メソッドのオーバーライドの際に
overrideキーワードの指定が必要である。
- ただし、インターフェイスのメソッドを実装する場合は、
overrideの指定は不要 (不可) である。
- メソッドは既定では非仮想であり、
virtualを指定することでオーバーライド可能な仮想メソッドとなる。 - プロパティ、インデクサ、イベントも、
virtual修飾されている場合はメソッドと同様にオーバーライドの対象となる。 sealedキーワードを指定することでオーバーライドを禁止できる。
コードの例を示す。
言語固有の注意点
あるスーパークラスとそれを継承したサブクラスを定義する際、JavaやC ではオーバーライドに関係した問題が起こりうるので注意が必要である(特にスーパークラスの実装者とサブクラスの実装者が異なる場合)。Javaのインスタンスメソッドは仮想メソッドであり、あとからスーパークラスにメソッドを追加したときに、そのメソッドと同じシグネチャのメソッドが既にサブクラスに存在すると、オーバーライドしたつもりがないのに関係のないメソッドをオーバーライドしてしまうという問題が起こる。逆にオーバーライドしたつもりでも、スーパークラスのメソッドシグネチャあるいはアクセシビリティの変更や、サブクラスのメソッド定義時のtypoなどによって正しくオーバーライドできていなかった、といった問題も起こる。後者の問題を回避するためにJavaでは@Overrideの指定が推奨されるが、後方互換性を保つため、アノテーションの指定は必須とはなっていない。C においてもC 11でoverride修飾子が導入されたが、override修飾子の指定はオプションであり必須ではない。
C#ではメソッドが既定で非仮想であり、またオーバーライドするには当初からoverride修飾子が必須なのでこの問題は起こらない。基底クラスを変更しても、破壊的な変更につながりにくくなっている。
KotlinやSwiftのような後発言語では、C#同様にオーバーライドにはoverrideの指定が必須となっている。
脚注
注釈
出典
関連項目
- オブジェクト指向プログラミング
- ポリモーフィズム
- メソッド (計算機科学)#仮想メソッド




