質問の歴史:
メソッドのオーバーライドはOOPの基本であり、Javaではもともとoverrideは必須ではありませんでした。Kotlinは厳密に型付けされた言語で、コードの明示性を高め、継承時の偶発的なエラーを避けるためにoverrideの使用を必須にしました。
問題:
明示的にoverrideを指定しないと、インターフェースやクラスの記述時に間違いを犯しやすくなります。名前や型、修飾子をタイプミスする可能性があります。プログラムはクラッシュしませんが、期待されるオーバーライドは機能しません。Kotlinはこの問題を根本的に解決します。
解決策:
Kotlinでは、メソッドがオーバーライド可能であるためには、open(またはabstract/interface)として宣言する必要があります。オーバーライドを行うためにはoverrideと明示的に記述する必要があります。シグネチャが一致しない場合はコンパイルエラーが発生します。これにより、Javaの多くのクラシックなバグを防ぎます。
コードの例:
open class Base { open fun greet() { println("Hello!") } } class Child : Base() { override fun greet() { println("Hi!") } }
主な特徴:
overrideを忘れた場合、偶然に関数をオーバーライドすることはできますか?
いいえ。overrideを省略した場合、宣言されたメソッドはクラスの新しいメソッドと見なされ、オーバーライドは発生しません - 基本メソッドにopenが存在する場合、コンパイラがエラーを出します。
コードの例:
open class A { open fun test() {} } class B : A() { fun test() {} // オーバーライドしていない! test2()と同様 }
自身のメソッドは親メソッドよりも厳格な可視性を持つことができますか?
いいえ。オーバーライドされるメソッドの可視性を狭めることはできません。例えば、基本メソッドがpublicの場合、overrideのオーバーライドはprivate/protected/internalにはできません。コンパイラがエラーを出します。
overrideコンポーネントはfinalであることができますか?
はい!さらなるオーバーライドを望まない場合は、finalを追加してください:
class D : Base() { final override fun greet() { //... } }
Javaにおいて:
public class Parent {void foo(){} } public class Child extends Parent {void foo(int x){} }
オーバーライドが期待されるが、実際にはオーバーロードです。呼び出しは間違ったメソッドに行きます。
プロ:
コント:
Kotlinにおいて:
open class Parent { open fun foo() {} } class Child : Parent() { override fun foo() { /*...*/ } }
プロ:
コント: