クラス まとめ
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宣言
継承
クラスは相互に派生させることができ、継承階層を構築することができる。