Обобщённые функции
Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 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 // generic: результат — IntЗадание
ЛегкоНапишите две обобщённые функции, работающие со списками любого типа. 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>())}")
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПервичные конструкторыБлоки init и валидацияВторичные конструкторыПовторение — читательский билет4Наследование
Открытые классы и подклассыПереопределение членовsuper и конструкторыАбстрактные классыПовторение — каталог сотрудников7Специальные классы
Классы данныхКлассы перечисленийЗапечатанные иерархииequals, hashCode, toStringПовторение — трекер заказов10Паттерны проектирования. Часть 2
Делегирование с помощью byПаттерн декораторПаттерн строительПаттерн состояние2Свойства и инкапсуляция
Пользовательские аксессорыМодификаторы видимостиПриватные сеттерыlazy и lateinitПовторение — банковский счёт5Интерфейсы
Объявление интерфейсовМетоды по умолчаниюМножественные интерфейсыИнтерфейсы как типыПовторение — способы оплаты8Обобщения
Обобщённые функцииОбобщённые классыОграничения типовВариативность с in и outПовторение — очередь с приоритетом11Проект: Управление библиотекой
Книги и читателиВыдача книг3Объекты и компаньоны
Объявления объектовОбъекты-компаньоныКонстанты с constОбъектные выраженияПовторение — билетная касса6Полиморфизм
Динамическая диспетчеризацияПроверка типов и умные приведения типовwhen с типамиФункции-расширенияПовторение — смотритель зоопарка9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Песочница Kotlin