ジェネリック関数
CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 37/57。
ジェネリック関数は、あらゆる型で動作します。その型パラメーターは、関数名の前に山括弧で記述され、呼び出し元が使用する型を表します。Tが通常使われる名前です。
fun <T> firstOr(list: List<T>, default: T): T = if (list.isEmpty()) default else list[0]mainの内部では:
println(firstOr(listOf(3, 5), 0) + 1)
println(firstOr(listOf<String>(), "none").uppercase())出力:
4
NONEKotlinは引数から型引数を推論します。推論する対象が何もない場合は、上記のlistOf<String>()のように、自分で記述します。
fun <T> repeatItem(item: T, times: Int): List<T> = List(times) { item }mainの中では:
println(repeatItem("ab", 3))
println(repeatItem(7, 2))
val empty = repeatItem<Double>(1.5, 0)
println(empty)出力:
[ab, ab, ab]
[7, 7]
[]関数には複数の型パラメーターを指定でき、関数型パラメーターではそれらを使用できます。これは、ライブラリ関数である map が、あらゆる要素型と結果型に対して動作する仕組みです。
fun <A, B> transform(items: List<A>, f: (A) -> B): List<B> {
val out = mutableListOf<B>()
for (item in items) out.add(f(item))
return out
}
fun <K, V> invert(map: Map<K, V>): Map<V, K> = map.entries.associate { (k, v) -> v to k }main の中で:
println(transform(listOf("kiwi", "fig")) { it.length })
println(invert(mapOf("a" to 1, "b" to 2)))出力:
[4, 3]
{1=a, 2=b}型パラメーターは呼び出し元の型を保持します。firstOr(listOf(3, 5), 0) は Int を返すため、+ 1 はコンパイルできます。List<Any> 用に記述したバージョンもすべてのリストを受け入れますが、Any を返すため、呼び出すたびにキャストが必要になります。
fun firstAny(list: List<Any>, default: Any): Any = if (list.isEmpty()) default else list[0]
// firstAny(listOf(3, 5), 0) + 1 // エラー: Any に plus がない
(firstAny(listOf(3, 5), 0) as Int) + 1 // コンパイルできるが、キャストが必要
firstOr(listOf(3, 5), 0) + 1 // ジェネリック: 結果は Intチャレンジ
簡単任意の型のリストで動作する、2つの汎用関数を記述してください。countWhere(items, predicate)は、述語である関数(T) -> Booleanを満たす要素の数を返します。mostCommon(items)は、最も多く出現する要素(出現回数が同じ場合は、リスト内で最初に現れる要素)を返します。空のリストの場合はnullを返します。
提供されたコードは、単語の行と数値の行を読み取り、3文字より長い単語の数、最も頻出する単語、偶数の数、最も頻出する数、そして空のリストに対してnothing: nullを出力します。
コードはListTools.ktに記述してください。Main.ktには提供された入力/出力コードが含まれており、編集できません。
自分で試してみよう
fun main() {
// 提供された入出力コード: そのままにしておく
val input = generateSequence(::readLine).toList()
val words = input[0].split(" ")
val numbers = input[1].split(" ").map { it.toInt() }
println("long words: ${countWhere(words) { it.length > 3 }}")
println("most common word: ${mostCommon(words)}")
println("even numbers: ${countWhere(numbers) { it % 2 == 0 }}")
println("most common number: ${mostCommon(numbers)}")
println("nothing: ${mostCommon(listOf<String>())}")
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Kotlinプレイグラウンド