10-3. コンストラクタとイニシャライザ
概要
Kotlin のクラスでは、オブジェクトを作成するためのコンストラクタと、オブジェクトの初期化を行うためのイニシャライザを定義できます。
コンストラクタは、オブジェクトが作成される際に呼び出され、オブジェクトの初期状態を設定します。
イニシャライザは、コンストラクタによって初期化されたオブジェクトに対して、追加の初期化処理を実行します。
Kotlin にはプライマリコンストラクタとセカンダリコンストラクタがあります。クラスは 1つ以上のプライマリコンストラクタと、0個以上のセカンダリコンストラクタを持つことができます。
プライマリコンストラクタ
プライマリコンストラクタは、クラスヘッダーの一部として定義されるコンストラクタです。
クラス名に続けて constructor のキーワード及びその直後のカッコ () 内に記載したコードブロックがプライマリコンストラクタとなります。
class クラス名 constructor(var プロパティ名: 型名 = 値,var プロパティ名: 型名 = 値,...) {
...
}
クラスをインスタンス化するときにパラメータを渡したい場合、その引数としてプロパティの型およびデフォルト値を定義できます。
コンストラクタに可視性修飾子 (private など) やアノテーションを指定しな場合は、constructor というキーワード自体を省略することができます。
例えば、ここまでに記載してきた Person クラスに関して、プロパティの初期化をコンストラクタで行うことができます。
変更前) プライマリコンストラクタ無し
fun main(){ val myPersonObj : Person = Person() myPersonObj.name = "HogeHoge" // 変更前はクラスのインスタンス化後 ここでプロパティを設定 myPersonObj.age = 3 // 変更前はクラスのインスタンス化後 ここでプロパティを設定 myPersonObj.greeting() } class Person { var name : String = "" var age : Int = 0 fun greeting(){ println("Hello World! 私は ${name} です。年齢は ${age} 才です。") } }
変更後)
constructor (var name : String = “", var age : Int = 0) の部分がコンストラクタです。
fun main(){ val myPersonObj : Person = Person("HogeHoge", 3) // インスタンス化の際にコンストラクタに合わせて引数を渡す myPersonObj.greeting() } class Person constructor (var name : String = "", var age : Int = 0) { fun greeting(){ println("Hello World! 私は ${name} です。年齢は ${age} 才です。") } }
この例では キーワード constructor 自体も省略可能なので、以下でも同様です。
変更例2)
fun main(){ val myPersonObj : Person = Person("HogeHoge", 3) myPersonObj.greeting() } class Person (var name : String = "", var age : Int = 0) { // constructor というキーワードも省略 fun greeting(){ println("Hello World! 私は ${name} です。年齢は ${age} 才です。") } }
セカンダリコンストラクタ
Kotlin のクラスでは、0個以上のセカンダリコンストラクタを持つこともできます。
セカンダリコンストラクタは、クラスの定義ブロック部分 (波かっこ{ } 内) に、constructor のキーワードに続けて記載します。
セカンダリコンストラクタでは、プライマリコンストラクタ (あるいは、ほかのセカンダリコンストラクタ) を呼ぶ必要があります。
クラスのインスタンス化の際に、引数の数を変えたい、ある引数をオプションとしたい場合などに、セカンダリコンストラクタが有用になります。
自分自身のクラスのプライマリコンストラクタは、
this (プライマリコンストラクタのパラメータ)
で呼び出せます。
セカンダリコンストラクタは以下のような記載になります。
constructor (セカンダリコンストラクタのパラメータとデフォルト値の指定) : this(プライマリコンストラクタのパラメータ)
例)
以下は、セカンダリコンストラクタとして Person クラスのインスタンス化の際の name だけを指定できるようにした例です。
(その際、年齢は 5 に設定されます。)
fun main(){ val myPersonObj : Person = Person("HogeHoge", 3) //プライマリコンストラクタでインスタンス化される val myPersonObj2 : Person = Person("FugaFuga") //セカンダリコンストラクタも実行される myPersonObj.greeting() myPersonObj2.greeting() } class Person (var name : String = "", var age : Int = 0) { constructor (name :String = "") : this(name, 5) fun greeting(){ println("Hello World! 私は ${name} です。年齢は ${age} 才です。") } }
出力結果)
Hello World! 私は HogeHoge です。年齢は 3 才です。
Hello World! 私は FugaFuga です。年齢は 5 才です。
イニシャライザ
コンストラクタでは、クラスのインスタンス化の際にプロパティの型やデフォルト値の指定ができますが、インスタンス化の際に実施しておきたい処理がある場合は、イニシャライザを利用します。
イニシャライザは、クラスの定義ブロック内に、キーワード init に続けて 波かっこ { } でコードブロックを記載します。
複数のイニシャライザブロックを定義することもできます。 イニシャライザブロックは、クラスの本体に記述された順序で実行されます。
例)
プロパティを出力するようにした例です。
fun main(){ val myPersonObj : Person = Person("HogeHoge", 3) //プライマリコンストラクタでインスタンス化される val myPersonObj2 : Person = Person("FugaFuga") //セカンダリコンストラクタも実行される myPersonObj.greeting() myPersonObj2.greeting() } class Person (var name : String = "", var age : Int = 0) { constructor (name :String = "") : this(name, 5) init { println ("name として ${name} が設定されました。") println ("age として ${age} が設定されました。") } fun greeting(){ println("Hello World! 私は ${name} です。年齢は ${age} 才です。") } }
出力結果)
name として HogeHoge が設定されました。
age として 3 が設定されました。
name として FugaFuga が設定されました。
age として 5 が設定されました。
Hello World! 私は HogeHoge です。年齢は 3 才です。
Hello World! 私は FugaFuga です。年齢は 5 才です。