クラス まとめ

kotlinlang.org

Classes

classキーワードを使ってクラスを宣言する。

class Invoice { /*....*/ }
  • class header: 型パラメーター, プライマリーコンストラクタ,など
  • class body

headerもbodyもオプションなので、省略が可能。

class Empty

Constructors

以下のコンストラクタを持つ

プライマリーコンストラク

プライマリコンストラクタは、ヘッダーに宣言する。 またプライマリコンストラクタが存在しない場合は、宣言が不要。

class Person constructor(firstName: String) { /*...*/ }

constructorキーワードは大抵の場合において、省略可能。

class Person(firstName: String) { /*...*/ }

プライマリーコンストラクタにはコードを含めることはできない。 初期化コードは、initキーワードを付けた初期化ブロックに配置する。

初期化ブロックは、コードに配置された順番に実行される。

class InitOrderDemo(name: String) {
    // property initializer
    val firstProperty = "First property: $name".also(::println)

    // class initializer
    init {
        println("First initializer block that prints ${name}")
    }

    // property initializer
    val secoundProperty = "Secound property: ${name.length}".also(::println)

    // class initializer
    init {
        println("Second initializer block that prints ${name.length}")
    }
}

InitOrderDemo("hello")

/* 実行結果
First property: hello
First initializer block that prints hello
Secound property: 5
Second initializer block that prints 5
*/

プリマリーコンストラクタのパラメーターは初期化ブロック内部で使用することができる。 またプロパティ初期化でも使用できる。

class Customer(name: String) {
    // property initializers
    val customerKey = name.uppercase()
}

プライマリコンストラクタ内部でプロパティの宣言と初期化が同時に行うことができる。

class Person(val firstName: String, val lastName: String, var age: Int) 

val tanaka = Person("tanaka", "yasushi", 27)

// valプロパティは変更不可
// tanaka.firstName = "yosida"
// varプロパティは変更可
tanaka.age += 1

トレーリングコンマをクラスのプロパティ宣言につけることができる。

class Person(
    val firstName: String,
    val lastName: String,
    var age: Int, // trailing comma

コンストラクタにアノテーションもしくは可視化修飾子(visibility modifiers)がついている場合は、constructorキーワードが必須。

修飾子は、constructorキーワードの前につける。

class Customer private @Inject constructor(name: String) { /*...*/ }
  • 可視化修飾子: デフォルトはpublic

セカンダリコンストラク

constructorキーワードを使って、複数のセカンダリコンストラクタを宣言することができる。

class Pet {
    // セカンダリコンストラクタ
    constructor(owner: Person) {
        owner.pets.add(this)
    }
}

// NG
// val cat = Pet()

// OK
val tanak = Person()
val cat = Pet(tanaka)

プライマリコンストラクタを持つ場合は、 セカンダリコンストラクタ内部で必ず呼び出す必要がある。 この際、thisキーワードを使用する。

class Person(val name:String) {
    constructor(name: String, age: Int) : this(name + age.toString()) {}
}

// プライマリコンストラクタのみ呼び出される
val yoshida = Person("yoshida")
println(yoshida.name) // yoshida

// セカンダリコンストラクタが呼び出される
val tanaka = Person("tanaka", 27)
println(tanaka.name) // tanaka27

セカンダリコンストラクタは、初期化コードがすべて実行されたあとで実行される。

class Constructors {

    constructor(i: Int) {
        println("Constructor $i")
    }

    init {
        println("Init block")
    }
}

val c = Constructors(5)

/* 実行結果 
Init block
Constructor 5
*/

抽象クラスでないクラスが、プライマリ、セカンダリ両方のコンストラクタを持たない場合、 引数なしのプライマリーコンストラクタが生成される。

もし、publicなコンストラクタを持ちたくない場合は、privateをつけてプライマリーコンストラクタを実装する。

class DontCreateMe private constructor () { /*...*/ }

// Cannot access '<init>': it is private in 'DontCreateMe'
val c = DontCreateMe()

クラスのインスタンス生成

通常の関数と同様にコンストラクタを呼び出すことで生成することができる

val invoice = Invoice()

val customer = Customer("Joe Smith")

Note: Kotlinはnewキーワードが不要。

クラスメンバ

  • コンストラク
  • 初期化ブロック
  • 関数
  • プロパティ
  • ネスト内部クラス
  • Object宣言

継承

クラスは相互に派生させることができ、継承階層を構築することができる。