Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
拡張関数
Kotlinの「拡張関数」は、既存のクラスを継承せずにメソッドを追加できる機能です。レシーバー型(拡張する型)を指定した通常の関数として定義し、そのクラスのメソッドのように呼び出せます。
構文
// 拡張関数の定義(String を拡張する例)
fun String.hello(): String = "Hello, $this!"
// 呼び出し
"Kotlin".hello() // "Hello, Kotlin!"
// 引数ありの拡張関数
fun String.repeat(n: Int): String = this.repeat(n)
// 拡張プロパティ(getterのみ定義可能)
val String.wordCount: Int
get() = this.split(" ").size
// Nullable型への拡張関数
fun String?.isNullOrBlankCustom(): Boolean = this == null || this.isBlank()
構文一覧
| 構文 | 概要 |
|---|---|
| fun 型名.関数名() | 拡張関数の定義です。「型名.」がレシーバー型の指定です。 |
| this | 拡張関数内でレシーバーオブジェクト(呼び出し元)を指します。 |
| val 型名.プロパティ名 | 拡張プロパティの定義です。状態は持てず getter のみ定義できます。 |
| Nullable 拡張関数 | 型名を「型?」にすると null 値に対しても呼び出せます。 |
サンプルコード
// String の拡張関数
fun String.isPalindrome(): Boolean = this == this.reversed()
fun String.capitalize2(): String = if (isEmpty()) this else this[0].uppercaseChar() + substring(1)
fun String.words(): List<String> = this.trim().split(Regex("\\s+"))
// Int の拡張関数
fun Int.isPositive(): Boolean = this > 0
fun Int.factorial(): Long {
require(this >= 0) { "負の数の階乗は未定義です" }
return if (this <= 1) 1L else (1..this).fold(1L) { acc, i -> acc * i }
}
// 拡張プロパティ
val String.wordCount: Int
get() = if (isBlank()) 0 else words().size
val Int.isOdd: Boolean
get() = this % 2 != 0
// List の拡張関数
fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null
fun main() {
// String の拡張関数
println("racecar".isPalindrome()) // true
println("hello".isPalindrome()) // false
println("hello world".capitalize2()) // Hello world
val sentence = " Hello Kotlin World "
println(sentence.words()) // [Hello, Kotlin, World]
println(sentence.wordCount) // 3
// Int の拡張関数
println(5.isPositive()) // true
println((-3).isPositive()) // false
println(5.factorial()) // 120
println(7.isOdd) // true
// List の拡張関数
val list = listOf("a", "b", "c")
println(list.secondOrNull()) // b
println(emptyList<String>().secondOrNull()) // null
// 標準ライブラリのような使い方
val numbers = listOf(1, 2, 3, 4, 5)
println(numbers.filter { it.isOdd }) // [1, 3, 5]
}
概要
拡張関数はJavaのユーティリティクラス(例: StringUtils.isNotEmpty())をメソッドのような構文で呼べるようにする仕組みです。コンパイル後は静的関数として展開されるため、実際にクラスを変更したりオーバーライドしたりはしません。
ジェネリクスを使った拡張関数『fun <T> List<T>.xxx()』は型を抽象化した汎用メソッドを追加できます。Kotlinの標準ライブラリ(『map()』『filter()』など)もほとんどが拡張関数として実装されています。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。