kotlin передача функции как параметра

Функциональное программирование

Функции и их параметры

Например, определим и вызовем функцию, которая просто выводит некоторую строку на консоль:

Функции можно определять в файле вне других функций или классов, сами по себе, как например, определяется функция main. Такие функции еще называют функциями верхнего уровня (top-level functions).

Здесь кроме главной функции main также определена функция hello, которая не принимает никаких параметров и ничего не возвращает. Она просто выводит строку на консоль.

Функция hello (и любая другая определенная функция, кроме main) сама по себе не выполняется. Чтобы ее выполнить, ее надо вызвать. Для вызова функции указывается ее имя (в данном случае «hello»), после которого идут пустые скобки.

Таким образом, если необходимо в разных частях программы выполнить одни и те же действия, то можно эти действия вынести в функцию, и затем вызывать эту функцию.

Предача параметров

Консольный вывод программы:

Аргументы по умолчанию

В примере выше при вызове функций showMessage и displayUser мы обязательно должны предоставить для каждого их параметра какое-то определенное значение, которое соответствует типу параметра. Мы не можем, к примеру, вызвать функцию displayUser, не передав ей аргументы для параметров, это будет ошибка:

Однако мы можем определить какие-то параметры функции как необязательные и установить для них значения по умолчанию:

Консольный вывод программы

Именованные аргументы

При вызове функции в скобках мы можем указать название параметра и с помощью знака равно передать ему нужное значение.

При этом, как видно из последнего случае, необязательно все аргументы передавать по имени. Часть аргументов могут передаваться параметрам по позиции. Но если какой-то аргумент передан по имени, то остальные аргументы после него также должны передаваться по имени соответствующих параметров.

Также если до обязательного параметра функции идут необязательные параметры, то для обязательного параметра значение передается по имени:

Изменение параметров

По умолчанию все параметры функции равносильны val-переменным, поэтому их значение нельзя изменить. Например, в случае следующей функции при компиляции мы получим ошибку:

Однако если параметр предствляет какой-то сложный объект, то можно изменять отдельные значения в этом объекте. Например, возьмем функцию, которая в качестве параметра принимает массив:

Здесь функция double принимает числовой массив и увеличивает значение его первого элемента в два раза. Причем изменение элемента массива внутри функции приведет к тому, что также будет изменено значение элемента в том массиве, который передается в качестве аргумента в функцию, так как этот один и тот же массив. Консольный вывод:

Источник

Котлин Функции высшего порядка

Язык Kotlin имеет превосходную поддержку функционального программирования. Функции Kotlin могут храниться в переменных и структурах данных, передаваться в качестве аргументов и возвращаться из других функций более высокого порядка.

Функция высшего порядка —

Передача лямбда-выражения в качестве параметра в функцию высшего порядка —

Мы можем передать лямбда-выражение в качестве параметра в функцию высшего порядка.
Существует два типа лямбда-выражения, которые можно передать:

Kotlin программа лямбда-выражения, которая возвращает Unit-

// функция высшего порядка

lmbd() // вызывает лямбда-выражение

>
fun main(args: Array ) <

// вызвать функцию высшего порядка

higherfunc(lambda) // передача лямбды в качестве параметра

Выход:

Объяснение:
Давайте разберемся с вышеприведенной программой шаг за шагом:

В верхней части мы определяем лямбда-выражение, которое содержит print() для вывода строки в стандартный вывод.

затем мы определяем функцию высшего порядка, которая содержит один параметр.

lmbd — это локальное имя для принимающего лямбда-параметра.
() означает, что функция не принимает никаких аргументов.
Unit представляет, что функция не возвращает никакого значения.

В основной функции мы вызвали функцию высшего порядка, передав лямбда-выражение в качестве параметра.

Kotlin программа лямбда-выражения, которая возвращает целочисленное значение —

// функция высшего порядка

fun main(args: Array ) <

higherfunc(lambda) // передача лямбды в качестве параметра

Выход:

Объяснение:
Давайте разберемся с вышеприведенной программой шаг за шагом:

В верхней части мы определяем лямбда-выражение, которое возвращает целочисленное значение.

Затем мы определили функцию высшего порядка, которая принимает лямбда-выражение в качестве параметра.

lmbd — это локальное имя для принимающего лямбда-параметра.
(Int, Int) представляет, что функция принимает два параметра целочисленного типа.
-> Int представляет, что функция возвращает целочисленное значение.

В основной функции мы вызвали функцию высшего порядка, передав лямбду в качестве параметра.

Передача функции в качестве параметра функции высшего порядка —

Мы можем передать функцию в качестве параметра в функцию высшего порядка.
Существует два типа функций, которые можно передавать:

Kotlin программа прохождения функции, которая возвращает Unit-

// определение обычной функции

fun printMe(s:String): Unit<

// определение функции высшего порядка

// вызывать обычную функцию, используя локальное имя

>
fun main(args: Array ) <

// вызвать функцию высшего порядка

Выход:

Объяснение:
Вверху мы определяем обычную функцию printMe() которая принимает параметр типа String и возвращает Unit.

(s: String) является единственным параметром
Единица представляет тип возврата

Затем мы определяем функцию высшего порядка как

Из основной функции старшая функция вызывается передачей строки и функции в качестве аргументов.

Kotlin программа передачи функции, которая возвращает целочисленное значение

// определение обычной функции

fun add(a: Int, b: Int): Int<

// определение функции высшего порядка

fun higherfunc(addfunc:(Int,Int)-> Int)<

// вызывать обычную функцию, используя локальное имя

>
fun main(args: Array ) <

// вызвать функцию высшего порядка

Выход:

Объяснение:
В верхней части мы определяем регулярную функцию как

он принимает два параметра типа Integer и возвращает сумму обоих целых чисел

Затем мы определяем функцию высшего порядка как

Из основной функции мы вызываем функцию высшего порядка, передавая регулярную функцию в качестве параметра

Возврат функции из функции высшего порядка

Мы можем вернуть функцию из функции высшего порядка. При возврате функции мы должны указать типы параметров и тип возврата обычной функции в типе возврата функции высшего порядка.

Kotlin программа функции, возвращающей другую функцию

fun mul(a: Int, b: Int): Int<

// объявление функции высшего порядка

fun higherfunc() : ((Int,Int)-> Int)<

>
fun main(args: Array ) <

// вызвать функцию и сохранить возвращенную функцию в переменную

val multiply = higherfunc()

// вызывает функцию mul () путем передачи аргументов

Выход:

Объяснение:
В верхней части программы мы определяем функцию mul() которая принимает два параметра, а ее тип возвращаемого значения также является целым числом.

Затем мы определяем функцию высшего порядка с возвращаемым типом как функцию.

:: mul представляет, что возвращает функцию mul()
(Int, Int) представляет, что mul принимает два параметра целочисленного типа
Int представляет, что mul возвращает целочисленное значение.

В основной функции мы вызвали вышестоящую функцию, которая возвращает другую функцию и сохраняет ее в переменной multiply.

Источник

Kotlin передача функции как параметра

Если статья вам понравилась, то можете поддержать проект.

Коты забавные, поэтому ввели ключевое слово fun (есть спорное мнение, что на самом деле это сокращение от «function» для обозначения функций, которые являются аналогами методов в Java).

Объявление функции начинается с ключевого слова fun, затем идёт имя функции, в круглых скобках указываются параметры. Тип возвращаемого значения указывается после списка параметров и отделяется от него двоеточием. Функция всегда возвращает значение. Если вы сами не указали возвращаемое значение, то функция вернёт Unit, который схож с void, но является объектом.

Стандартный вывод «Hello Kitty» для Kotlin-программы (Desktop, не Android):

Данная функция ничего не возвращает. Напишем другую функцию, возвращающую результат.

Обратите внимание, что if является выражением в Kotlin, а не Java-оператором и соответствует тернарному оператору в Java:

Простую функцию, в которой блок состоит из одной строки кода, можно переписать в одну строчку.

Можно даже убрать возвращаемый тип. Гулять так гулять.

Такой способ подходит только для функций, в которых Kotlin способен самостоятельно разобраться, чего хотел разработчик, т.е. с телом-выражением в правой части. В правой части мы вычисляем какой-то результат, который обычно передавали в return. Теперь мы можем отказаться от return и фигурных скобок, и сразу присваивать результат функции.

В других случаях (тело-блок) вы обязаны указывать возвращаемый тип и использовать инструкцию return.

Функции верхнего уровня можно импортировать для сокращения кода.

Доступен вариант со звёздочкой.

Можно даже изменить имя и создать псевдоним при помощи ключевого слова as. Этот вариант может оказаться полезным, если имеются несколько одинаковых названий функций из разных пакетов и хочется избежать путаницы и конфликтов.

Именованные параметры

Мы привыкли, что при вызове метода следует соблюдать очерёдность параметров. С именованными параметрами такая необходимость отпала. Создадим новую функцию из двух параметров.

Вызывая функцию, мы можем не соблюдать порядок параметров, если явно будем прописывать имена параметров.

Несмотря на то, что мы поменяли местами параметры, итоговый результат всё равно будет работать правильно. Такой подход может пригодиться, когда вы не помните порядок и вам лень смотреть документацию.

Данный приём не сработает при работе с методами, написанными на Java. Поддержка именованных аргументов есть в Java 8, но Kotlin поддерживает совместимость с Java 6, поэтому приходится смириться. Возможно, в будущем, эта проблема решится автоматически, когда откажутся от поддержки старых версий.

Параметры по умолчанию

Добавим в класс активности новую функцию для вывода всплывающего сообщения (в примере используется функция-расширение).

Второй параметр использует значение по умолчанию и мы можем его не указывать при вызове. Вызываем функцию.

С параметрами по умолчанию нужно быть внимательными, возможна ситуация, когда Kotlin не поймёт, что вы от него хотите. Создадим функцию из трёх параметров, один из них будет иметь значение по умолчанию.

Вызываем функцию с двумя параметрами, надеясь, что третий подставится самостоятельно. Но Kotlin не может решить, какой параметр пропущен.

В этом случае на помощь приходят именованные параметры.

Третий параметр теперь нам известен, опущенный параметр относится ко второму, оставшийся относится к первому.

У класса Thread имеется восемь конструкторов! Вы можете создавать гораздо удобные решения с параметрами по умолчанию.

Unit. Если функция ничего не возвращает

Стоит немного рассказать о функциях, которые не возвращают никаких значений. В Java мы используем ключевое слово void для подобных случаев. В Kotlin был придуман новый тип Unit для подобных ситуаций. Получается, что функция всегда что-то возвращает, в нашем случае Unit, который мы никак не используем.

Но Kotlin достаточно умен и понимает, что мы не хотим ничего возвращать. Поэтому мы можем сократить код.

Можно сократить код, убрав фигурные скобки, так как у функции только одно выражение.

Вызываем функцию с любым количеством аргументов.

Если функция имеет и другие параметры, то они должны быть раньше vararg. Можно обойти это правило, если использовать именованные параметры, но лучше избегать таких ситуаций.

По сути vararg работает с массивом, но простое добавление массива Kotlin не пропустит. Следует использовать специальный оператор *.

Вложенные (локальные) функции

Внутри одной функции можно создать ещё одну локальную функцию.

Вложенная функция имеет доступ к переменным своей родительской функции.

Функции верхнего уровня

Функцию можно объявить в начале файла, не обязательно размещать его в теле класса. Это удобно, когда вам нужны методы, которые не относятся к конкретному классу или вы не хотите перезагружать имеющийся класс лишним кодом. Часто для этих целей программисты создавали отдельные классы со словом Util.

Размещая код метода за пределами класса, вы избегаете лишней вложенности. Они по-прежнему являются членами пакета, прописанного в файле и могут импортироваться при использовании в других пакетах.

Таким образом можно создать новый файл без всяких классов, указав только пакет.

Kotlin незаметно для вас создаст класс CatsKt по имени файла и все функции скомпилирует в статические методы. Если будете вызывать функцию в Java-коде, то это будет выглядеть следующим образом.

Если имя класса вас не устраивает, то добавьте аннотацию @JvmName перед именем пакета.

Тогда вызов в Java-коде будет другим.

Функция TODO()

В стандартную библиотеку Kotlin входит функция TODO() (надо сделать). Её описание выглядит следующим образом.

Функция TODO() возбуждает исключение, т.е. вызов функции гарантированно завершится ошибкой — она возвращает тип Nothing. Считайте функцию временной заглушкой. Разработчик знает, что некоторая функция должна вернуть строку или другой объект, но пока отсутствуют другие функции, необходимые для ее реализации. Создадим для примера две функции.

Обратите внимание, что возвращаемое значение для shouldReturnAString() — это String, но на самом деле функция ничего не возвращает. Аналогично у shouldReturnACat().

Возвращаемый тип Nothing у TODO() показывает компилятору, что функция гарантированно вызовет ошибку, поэтому проверять возвращаемое значение после TODO() не имеет смысла, так как shouldReturnAString() и shouldReturnACat() ничего не вернут. Компилятор не будет ругаться, а разработчик может продолжать разработку, отложив на потом реализацию функции-заглушки.

Функцию можно вызвать без аргументов. Код, который будет следовать за функцией, будет недостижим.

Имена функций в обратных кавычках

Можно объявить или вызвать функцию с именем, содержащим нестандартные символы. Для этого достаточно заключить имя в обратные кавычки `. Например, объявим функцию:

Данная возможность нужна, чтобы поддерживать совместимость с Java в тех моментах, когда встречаются зарезервированные ключевые слова. Использование обратных кавычек позволяют избежать несовместимости в случаях, если это необходимо. На практике такое почти не встречается.

На данный момент под Android такой способ не работает, студия будет ругаться.

Источник

Функции в Kotlin для начинающих

Функции являются основой многих языков программирования. Проще говоря, функция позволяет определить блок кода, который выполняет определенную задачу. Затем, если приложению требуется выполнить данную задачу, можно вызвать функцию вместо того, чтобы копировать и вставлять везде одинаковый код.

Содержание статьи

В этом уроке вы узнаете, как создавать собственные функции, и увидите, как Kotlin упрощает их использование.

Создание новой функции в Kotlin

Представьте, что у вас есть приложение, которому часто требуется выводить ваше имя. Для этого можно создать функцию:

Приведенный выше код известен как объявление функции.

Подробнее о необходимости этих скобок обсудим ниже.

После круглых скобок следует открывающая фигурная скобка, за которой идет код, который нужно запустить в функции, а затем закрывающая скобка. После определения функции ее можно вызвать следующим образом в главной функции main() :

Вывод будет следующим:

В прошлых уроках мы уже использовали функции. Функция println выводит результат на консоль. Ниже вы узнаете, как передавать данные в функцию и получать данные взамен.

Параметры функции в Kotlin

В предыдущем примере, функция просто выводит на экран сообщение. Это здорово, но зачастую для функции требуется настроить параметры, с помощью которых она будет работать по-разному в зависимости от данных, которые в нее передаются.

В качестве примера рассмотрим следующую функцию:

Здесь дается определение одного параметра value типа Int в круглых скобках после названия функции. В любой функции круглые скобки содержат так называемый список параметров. Эти круглые скобки необходимы как при объявлении, так и при вызове функции, даже если список параметров пуст.

Данная функция выведет любое заданное число умноженное на пять. В этом примере вызывается функция с аргументом 10, поэтому вывод будет следующим:

На заметку: Не путайте термины «параметр» и «аргумент». Функция объявляет свои параметры в списке параметров. При вызове функции вы предоставляете значения в качестве аргументов для параметров функции.

Можно написать функцию более обобщенной. С двумя параметрами, функция выведет результат умножение любых двух значений.

Иногда при вызове функции будет правильнее использовать именованные аргументы, это упрощает понимание назначения каждого аргумента.

Теперь при вызове функции очевидно, для чего нужны аргументы. Это особенно полезно, когда у функции несколько параметров.

Вы также можете назначить параметрам значения по умолчанию:

Мы добавили = 1 после второго параметра. Это значит, что при отсутствии значения для второго параметра значение по умолчанию будет равно 1.

Таким образом, вывод кода будет следующим:

Иметь значение по умолчанию может быть полезно, когда вы ожидаете, что у параметра будет одно конкретное значение большую часть времени, и это упростит код при вызове функции.

Функции и оператор возврата return в Kotlin

Все рассматриваемые до сих пор функции выполняли простую задачу — они что-то выводили в консоль. Функции также могут возвращать значение. При вызове функции можно присвоить возвращаемое значение переменной или константе или использовать его непосредственно в if или when выражениях в качестве значения для проверки.

Это означает, что функцию можно использовать для управления данными. Данные просто принимаются через параметры, они изменяются внутри функции, а затем возвращаются.

Определить функцию, возвращающую значение, можно следующим образом:

Внутри функции используется оператор return для возврата значения. В этом примере возвращается результат от умножения двух параметров.

Также можно вернуть несколько значений с помощью Pair:

Параметры в качестве значений в Kotlin

Рассмотрим следующим пример кода:

Результатом выполнения данного кода будет ошибка:

Обычно такое поведение ожидаемо. В идеале функция не меняет свои параметры. Если это так, то вы не можете быть уверены в значениях параметров и можете сделать неверные предположения касательно кода, что приведет к ошибочным данным при их использовании.

Если нужно, чтобы функция изменила параметр и вернула его, вы должны сделать это косвенно, объявив новую переменную следующим образом:

На заметку: Как вы увидите в будущем, при добавлении параметров к основному конструктору при определении класса вы действительно добавляете var или val к параметрам. Это делается для указания, что параметры являются свойствами класса и что их значение может или не может быть изменена.

Перегрузка функций в Kotlin

Что делать, если вам нужно использовать несколько функций с одним и тем же названием?

Это перегрузка, которая дает возможность определить похожие функции, используя одинаковое название для них, НО с разными типами параметров.

Однако, компилятор по-прежнему должен видеть разницу между данными функциями внутри текущей области видимости. Каждый раз при вызове функции должно быть понятно, какая функция будет выполняться.

Обычно это достигается через разницу в списке параметров:

На заметку: Одного возвращаемого типа недостаточно для различия двух функций. Т.е. если одна функция возвращает Int а другая возвращает строку — этого будет недостаточно, чтобы компилятор понял какую из них вызвать ведь тип у параметров один и тот же.

К примеру, такое определение двух методов приведет к ошибке:

У методов выше одинаковые названия, типы параметров и количество параметров. Kotlin не может различить их!

Стоит отметить, что перегрузку нужно использовать осторожно. Используйте перегрузку только для тех функций, поведение которых похоже но из за разных типов у параметров у них будет разная обработка данных внутри функции.

Задания для проверки

Функции как переменные в Kotlin

Функции в Kotlin являются просто еще одним типом данных. Их можно присваивать переменным и константам как и значения любого другого типа вроде Int или String.

Рассмотрим следующую функцию:

Данная функция принимает два параметра и возвращает сумму их значений.

Вы можете присвоить данную функцию переменной через использование метода создания ссылки :: следующим образом:

Теперь можно использовать переменную function так же, как использовалась бы функция add :

Данный код выведет на экран: 6

Теперь рассмотрим следующий код:

Назначение функций переменным может быть очень удобным, потому что таким образом вы можете передавать функции другим функциям. Далее дан показательный этому пример:

Функция printResult принимает три параметра:

Возможность передавать функции другим функциям очень полезна. Вы можете не только передавать данные для различных манипуляций с ними, но и функции в качестве параметров. Это также означает, что вы можете гибко выбирать какой именно код будет выполняться.

Присваивание функций переменным и передача функций в качестве аргументов — это один из аспектов функционального программирования, о котором вы подробнее узнаете в будущих уроках.

Невозвращаемые функции в Kotlin

Это может показаться запутанным, но мы все-таки рассмотрим пример функции, которая предназначена для сбоя работы приложения. Если приложение собирается работать с поврежденными данными, зачастую лучше завершить работу вместо продолжения работы в неизвестном и потенциально опасном состоянии.

Другим примером невозвращаемой функции является функция, которая обрабатывает цикл событий. Цикл событий лежит в основе каждого современного приложения, которое принимает данные от пользователя и отображает их на экране. Цикл событий обслуживает запросы, поступающие от пользователя, а затем передает эти события в код приложения, который вызывает отображение информации на экране. Затем цикл возвращается назад и обслуживает следующее запросы.

Эти циклы событий часто запускаются в приложении путем вызова функции, которая никогда не возвращается. Если вы начинаете разрабатывать приложения для Android, помните об этом, когда столкнетесь с основным потоком, также известным как поток UI, или поток пользовательского интерфейса.

У Kotlin есть способ сообщить компилятору, что функция никогда не вернет значение. Вы устанавливаете тип возвращаемого значения функции на тип Nothing, указывая на то, что функция никогда ничего не возвращает.

Грубая, но честная реализация невозвращаемой функции будет выглядеть следующим образом:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *