1. let 関数
let 関数は、特定のスコープ内で変数を定義する場合や null チェックを簡略化するために使用されます。
1.1 使用例
object.let {
it.todo() // it で object のプロパティやメソッドにアクセス
}
// null チェック
object?.let {
it.todo()
}
1.2 インライン関数とラムダ式
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
1.3 使用シーン
- 可空オブジェクトの null チェック
- 特定のスコープ内の変数の定義
obj?.funA()
obj?.funB()
obj?.funC()
obj?.let {
it.funA()
it.funB()
it.funC()
}
2. with 関数
2.1 使用例
with(object) {
// todo
}
2.2 インライン関数とラムダ式
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
2.3 使用シーン
同じクラスの複数のメソッドを呼び出す際に、クラス名の繰り返しを避けることができます。
obj.funA()
obj.funB()
obj.funC()
with(obj) {
this.funA()
funB() // this は省略可能
funC()
}
3. run 関数
3.1 使用例
object.run {
// todo
}
3.2 インライン関数とラムダ式
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
3.3 使用シーン
obj?.funA()
obj?.funB()
obj?.funC()
obj?.run {
this.funA()
funB() // this は省略可能
funC()
}
4. apply 関数
4.1 使用例
object.apply {
// todo
}
4.2 インライン関数とラムダ式
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
apply 関数は、run 関数と似ていますが、戻り値が異なる点が特徴です。apply 関数はオブジェクト自身を返します。
5. also 関数
5.1 使用例
object.also {
// todo
}
5.2 インライン関数とラムダ式
@kotlin.internal.InlineOnly
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
also 関数は、let 関数と似ていますが、戻り値が異なる点が特徴です。also 関数はオブジェクト自身を返します。
6. 比較まとめ
| 関数名 | インライン定義 | 関数内でのオブジェクト参照 | 戻り値 | 拡張関数か |
|---|---|---|---|---|
| let | fun T.let(block: (T) -> R): R = block(this) | it で現在のオブジェクトを指す | ラムダ式の戻り値 | はい |
| with | fun with(receiver: T, block: T.() -> R): R = receiver.block() | this または省略 | ラムダ式の戻り値 | いいえ |
| run | fun T.run(block: T.() -> R): R = block() | this または省略 | ラムダ式の戻り値 | はい |
| apply | fun T.apply(block: T.() -> Unit): T | this または省略 | オブジェクト自身 | はい |
| also | fun T.also(block: (T) -> Unit): T | it で現在のオブジェクトを指す | オブジェクト自身 | はい |
7. 実用例: Kotlin でのシングルトンの実装
Kotlin では `object` や `by lazy` を使用して簡単にシングルトンを実装できます。しかし、初期化時に他の操作も行いたい場合があります。
class Singleton private constructor() {
companion object {
@Volatile
private var instance: Singleton? = null
fun getInstance(context: Context): Singleton {
return instance ?: synchronized(this) {
instance ?: Singleton().also {
// 初期化処理
instance = it
}
}
}
}
}