クラスの定義
class MyClass
val myClass = MyClass() // デフォルトのコンストラクタが生える
Kotlinではnew
キーワードを付ける必要はない
new
は予約語ではない
メソッド
- 定義方法は関数と同じ
- 呼び出しは
インスタンス.メソッド名
class Greeter {
fun greet(name: String) {
println("Hello, $name")
}
}
val greeter = Greeter()
greeter.greet("Kotlin")
プロパティ
- 定義方法は変数と同じ
- オブジェクトの特性や性質を表すデータをやり取りするための窓口
class Person {
var name: String = ""
var age: Int = 0
}
val hanako = Person()
println(hanako.name) // ""
println(hanako.age) // 0
hanako.name = "hanako"
hanako.age = 25
println(hanako.name) // "hanako"
println(hanako.age) // 25
バッキングフィールド
- 上記の例のような
Person
クラスのname
やage
には自動的にバッキングフィールドが生成される - 例えば、
name
として保持する文字列オブジェクトへの参照をバッキングフィールドが持っている - バッキングフィールドを持たないプロパティを定義することも可能
```Kotlin:バッキングフィールドを持たないnameLength
追加
class Person {
var name: String = ""
var age: Int = 0
val nameLength: Int
get(): Int {
return this.name.length
}
}
これはSwiftでいうコンピューテッドプロパティに似ている
カスタムセッターを定義することも可能
```Kotlin
class Person {
var name: String = ""
set(value) {
println("${value}がセットされました")
field = value
}
var age: Int = 0
val nameLength: Int
get(): Int {
return this.name.length
}
}
- fieldはバッキングフィールドを表す暗黙の変数
-
name = value
とすると無限にカスタムセッターが呼ばれてクラッシュする
-
遅い初期化
- バッキングフィールドをもつプロパティは初期化が必須
- どうしても初期化を遅らせたい場面がある
- DIやUnitテストのときとか…
-
var
のみ可能 - 初期化前に
lateinit
の変数にアクセスするとkotlin.UninitializedPropertyAccessException
をスローする
class MyClass {
lateinit var foo: String
}
this
- メソッドやプロパティをまとめてメンバと呼ぶ
- メンバへのアクセスは
目的のオブジェクトへの参照.メンバ名
-
this.メンバ名
とすることで、自身のオブジェクトのメンバにアクセスできる -
this
は省略可能
コンストラクタとイニシャライザ
- 分数クラス
Rational
の初期化に分子numerator
と分母denominator
を受け取る例
class Rational constructor(n: Int, d: Int) {
val numerator: Int = n
val denominator: Int = d
}
val half = Rational(1, 2)
println(half.numerator)
println(half.denominator)
コンストラクタの引数をそのままプロパティにしたい場合は、引数にval
やvar
をつける
class Rational(val numerator: Int, val denominator: Int)
セカンダリコンストラクタ
- 今までのコンストラクタはプライマリコンストラクタ
- 分母の指定がない場合はデフォルトで1になるセカンダリコンストラクタを定義
class Rational(val numerator: Int, val denominator: Int) {
constructor(numerator: Int): this(numerator, 1)
}
// 今回の場合だとデフォルト引数のほうが早い
class Rational(val numerator: Int, val denominator: Int = 1)
イニシャライザ
- インスタンス生成の際に実施しておきたい処理
class Rational(val numerator: Int, val denominator: Int = 1) {
init {
// 要求に反した場合、例外をスローする標準ライブラリの関数
// ∴分母が0になった場合、IllegalArgumentExceptionをスローする
require(denominator != 0)
}
}
エクステンション
既存クラスに対して、その定義に手を入れずにメソッドを追加できる→拡張関数
fun String.countWords(): Int = this.split("""\s+""".toRegex()).size
"I like Kotlin".countWords() // 3
拡張プロパティもOK
this
は省略可能
val String.wordsCount: Int
get() = split("""\s+""".toRegex()).size