Как работают SAM-conversions?
Single Abstract Method (SAM) интерфейсы — это интерфейсы только с одним абстрактным методом (функциональные интерфейсы). Kotlin поддерживает соглашение SAM — автоматическую конвертацию функций и lambda между Kotlin и Java.
SAM-conversions позволяют использовать Java-интерфейсы с единственным абстрактным методом в Kotlin, как если бы это были функциональные типы. В Kotlin вы можете использовать такие интерфейсы для создания лямбда-выражений без явного определения функционального типа.
При использовании интерфейса с единственным абстрактным методом в качестве функционального интерфейса в Java, вы можете передавать его экземпляры вместо лямбда-выражений. Это тоже возможно в Kotlin, но на самом деле Kotlin предоставляет более простой синтаксис для этого. Когда вам нужно использовать функциональный интерфейс в Kotlin, вы можете передать lambda-выражение, которое соответствует сигнатуре единственного метода интерфейса, вместо экземпляра интерфейса. Компилятор сам преобразует лямбда-выражение в экземпляр интерфейса, используя функцию-расширение метода invoke интерфейса. Пример:
Single Abstract Method (SAM) интерфейсы — это интерфейсы только с одним абстрактным методом (функциональные интерфейсы). Kotlin поддерживает соглашение SAM — автоматическую конвертацию функций и lambda между Kotlin и Java.
SAM-conversions позволяют использовать Java-интерфейсы с единственным абстрактным методом в Kotlin, как если бы это были функциональные типы. В Kotlin вы можете использовать такие интерфейсы для создания лямбда-выражений без явного определения функционального типа.
При использовании интерфейса с единственным абстрактным методом в качестве функционального интерфейса в Java, вы можете передавать его экземпляры вместо лямбда-выражений. Это тоже возможно в Kotlin, но на самом деле Kotlin предоставляет более простой синтаксис для этого. Когда вам нужно использовать функциональный интерфейс в Kotlin, вы можете передать lambda-выражение, которое соответствует сигнатуре единственного метода интерфейса, вместо экземпляра интерфейса. Компилятор сам преобразует лямбда-выражение в экземпляр интерфейса, используя функцию-расширение метода invoke интерфейса. Пример:
interface OnClickListener {
fun onClick(view: View)
}
class Button {
fun setOnClickListener(listener: OnClickListener) {
// ...
}
}
val button = Button()
button.setOnClickListener { view ->
// обработка нажатия кнопки
}
В этом примере мы определяем интерфейс OnClickListener с единственным абстрактным методом onClick. Затем мы создаем класс Button, который может иметь слушатель, реализующий данный интерфейс. После этого мы создаем экземпляр Button и передаем лямбда-выражение с соответствующей сигнатурой в качестве слушателя. Компилятор автоматически преобразует это лямбда-выражение в экземпляр интерфейса OnClickListener, используя функцию-расширение invoke интерфейса.Koin: Простой и легковесный фреймворк для внедрения зависимостей
Принцип внедрения зависимостей становится все более неотъемлемой частью процесса разработки. Без него сложно представить себе достижение желанного разделения обязанностей в коде или обеспечение должного уровня тестируемости.
В то же время, хотя Spring Framework и является широко распространенным выбором, он далеко не всем подходит. Некоторым было бы предпочтительнее использовать более простые и легковесные фреймворки с продвинутой поддержкой асинхронных операций ввода-вывода. Другие были бы признательны за статическое разрешение зависимостей для более быстрого запуска приложения.
Читать статью
Принцип внедрения зависимостей становится все более неотъемлемой частью процесса разработки. Без него сложно представить себе достижение желанного разделения обязанностей в коде или обеспечение должного уровня тестируемости.
В то же время, хотя Spring Framework и является широко распространенным выбором, он далеко не всем подходит. Некоторым было бы предпочтительнее использовать более простые и легковесные фреймворки с продвинутой поддержкой асинхронных операций ввода-вывода. Другие были бы признательны за статическое разрешение зависимостей для более быстрого запуска приложения.
Читать статью
Teletype
Koin: Простой и легковесный фреймворк для внедрения зависимостей
Принцип внедрения (инжектирования) зависимостей становится все более неотъемлемой частью процесса разработки. Без него сложно...
Указатели на функции (Function references, Bound callable references)
В языке Kotlin есть возможность работать с функциями как с объектами. Функции можно сохранять в переменные, передавать как аргументы и возвращать из других функций. Для этого можно использовать функциональные ссылки (Function references), которые представляют собой указатель на функцию.
1. Function references
Синтаксис функциональной ссылки имеет следующий вид:
Bound callable references (привязанные ссылки) — это то же самое понятие, что и указатели на методы, но в случае, когда метод вызывается на экземпляре класса. В этом варианте мы можем использовать ссылку на метод, связанную с конкретным экземпляром класса. Для создания привязанной ссылки на метод используется следующий синтаксис: <object_name>::<method_name>.
Допустим, что у нас есть экземпляр класса person типа Person. Тогда мы можем использовать ссылку на метод getName() для получения его имени:
В языке Kotlin есть возможность работать с функциями как с объектами. Функции можно сохранять в переменные, передавать как аргументы и возвращать из других функций. Для этого можно использовать функциональные ссылки (Function references), которые представляют собой указатель на функцию.
1. Function references
Синтаксис функциональной ссылки имеет следующий вид:
::function_name. Указатели на функции представляют собой сокращенную форму записи вызова функции. Вместо того, чтобы объявлять лямбда-выражение и передавать его как аргумент функции, можно использовать ссылку на существующий метод. Например, у нас есть класс Person с методом getName():class Person(val name: String) {
fun getName(): String = name
}
Тогда мы можем использовать указатель на метод getName() вместо лямбда-выражения:val persons = listOf(Person("Alice"), Person("Bob"))
val names = persons.map(Person::getName)
2. Bound callable referencesBound callable references (привязанные ссылки) — это то же самое понятие, что и указатели на методы, но в случае, когда метод вызывается на экземпляре класса. В этом варианте мы можем использовать ссылку на метод, связанную с конкретным экземпляром класса. Для создания привязанной ссылки на метод используется следующий синтаксис: <object_name>::<method_name>.
Допустим, что у нас есть экземпляр класса person типа Person. Тогда мы можем использовать ссылку на метод getName() для получения его имени:
val person = Person("Alice")
val name = person::getName
Здесь name будет ссылаться на метод getName() объекта person.Задачи про PEG-парсеры
Когда-то я хотел сделать контест по парсингу для Codeforces. Придумал задания двух типов:
1. Дается неформальное описание языка, по которому нужно создать грамматику (например, "язык с правильными скобочными последовательностями")
2. Даны примеры строк в языке, по которым нужно восстановить грамматику
У обоих типов заданий есть свои проблемы, так что контест я не сделал.
В итоге я сделал игру программу, в которой можно решать задания второго типа, при этом проверять строки на принадлежность угадываемому языку.
Читать статью
Когда-то я хотел сделать контест по парсингу для Codeforces. Придумал задания двух типов:
1. Дается неформальное описание языка, по которому нужно создать грамматику (например, "язык с правильными скобочными последовательностями")
2. Даны примеры строк в языке, по которым нужно восстановить грамматику
У обоих типов заданий есть свои проблемы, так что контест я не сделал.
В итоге я сделал игру программу, в которой можно решать задания второго типа, при этом проверять строки на принадлежность угадываемому языку.
Читать статью
Teletype
Задачи про PEG-парсеры
Когда-то я хотел сделать контест по парсингу для Codeforces. Придумал задания двух типов:
Что такое inline функции, в чем их преимущество?
В Kotlin есть два типа функций: обычные и встроенные. Обычные функции похожи на функции в других языках программирования. Но встроенные функции имеют модификатор inline. Это позволяет компилятору подставить тело функции прямо в место её вызова.
Как работают inline функции?
Использование анонимных функций (лямбда-выражений) в Kotlin приводит к дополнительным затратам памяти. При использовании лямбда-выражения создается объект FunctionN (где N — количество параметров в лямбда-выражении), который содержит ссылку на само лямбда-выражение и может содержать захваченные переменные. При передаче лямбда-выражения в качестве параметра метода также создается новый объект FunctionN, что приводит к дополнительным затратам памяти.
Поэтому, чтобы избежать создания дополнительных объектов при передаче лямбда-выражений в функцию в качестве параметра, можно использовать встраивание (inline). Ключевое слово inline позволяет компилятору подставить тело функции непосредственно в место её вызова, вместо того, чтобы создавать объекты функций. Таким образом можно уменьшить затраты на создание объектов и улучшить производительность приложения.
Пример синтаксиса inline-функций с лямбдой:
В Kotlin есть два типа функций: обычные и встроенные. Обычные функции похожи на функции в других языках программирования. Но встроенные функции имеют модификатор inline. Это позволяет компилятору подставить тело функции прямо в место её вызова.
Как работают inline функции?
Использование анонимных функций (лямбда-выражений) в Kotlin приводит к дополнительным затратам памяти. При использовании лямбда-выражения создается объект FunctionN (где N — количество параметров в лямбда-выражении), который содержит ссылку на само лямбда-выражение и может содержать захваченные переменные. При передаче лямбда-выражения в качестве параметра метода также создается новый объект FunctionN, что приводит к дополнительным затратам памяти.
Поэтому, чтобы избежать создания дополнительных объектов при передаче лямбда-выражений в функцию в качестве параметра, можно использовать встраивание (inline). Ключевое слово inline позволяет компилятору подставить тело функции непосредственно в место её вызова, вместо того, чтобы создавать объекты функций. Таким образом можно уменьшить затраты на создание объектов и улучшить производительность приложения.
Пример синтаксиса inline-функций с лямбдой:
inline fun functionName(parameter1: Type1, parameter2: Type2, ..., parameterN: TypeN, block: () -> Unit): ReturnType {
// function body
}
Модификатор inline влияет и на функцию, и на лямбду, переданную ей: они обе будут встроены в место вызова.Ускоряем поиск по коду в Android Studio
Рассмотрим возможности Android Studio, позволяющие быстрее ориентироваться в коде: находить нужные фрагменты и выявлять связи между ними.
Если вы опытный пользователь, то вам известно большинство нижеперечисленных лайфхаков. Но я узнавал о многих возможностях случайно, через многие месяцы работы в Android Studio, поэтому хочу рассказать всё, везде и сразу.
Читать статью
Рассмотрим возможности Android Studio, позволяющие быстрее ориентироваться в коде: находить нужные фрагменты и выявлять связи между ними.
Если вы опытный пользователь, то вам известно большинство нижеперечисленных лайфхаков. Но я узнавал о многих возможностях случайно, через многие месяцы работы в Android Studio, поэтому хочу рассказать всё, везде и сразу.
Читать статью
Teletype
Ускоряем поиск по коду в Android Studio
Рассмотрим возможности Android Studio, позволяющие быстрее ориентироваться в коде: находить нужные фрагменты и выявлять связи между ними.
Модификатор noinline
Если же вы хотите, чтобы некоторые лямбды, переданные inline-функции, не были встроены, то отметьте их модификатором noinline.
Если же вы хотите, чтобы некоторые лямбды, переданные inline-функции, не были встроены, то отметьте их модификатором noinline.
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
// ...
}
Разница между ними в том, что встраиваемая лямбда может быть вызвана только внутри inline-функции, либо может быть передана в качестве встраиваемого аргумента. В то время как с noinline-функциями можно работать без ограничений: хранить внутри полей, передавать куда-либо и т.д.Создаем нативное Kotlin приложение на Spring Boot Native, Gradle и GraalVM без докера под MacOS и Windows
В этой статье я хочу рассказать о практическом опыте нативной компиляции production приложения, написанного на Kotlin со Spring Boot, Gradle с использованием GraalVM . Начну сразу с минусов и плюсов самой возможности нативной компиляции и где она может быть полезна, и дальше перейду уже непосредственно к процессу сборки под MacOS и Windows.
В конце статьи я более подробно расскажу о проекте и почему возникла такая необходимость, учитывая довольно много ограничений и подводных камней поддержки нативной компиляции как со стороны Spring Boot, та и со стороны GraalVM.
Читать статью
В этой статье я хочу рассказать о практическом опыте нативной компиляции production приложения, написанного на Kotlin со Spring Boot, Gradle с использованием GraalVM . Начну сразу с минусов и плюсов самой возможности нативной компиляции и где она может быть полезна, и дальше перейду уже непосредственно к процессу сборки под MacOS и Windows.
В конце статьи я более подробно расскажу о проекте и почему возникла такая необходимость, учитывая довольно много ограничений и подводных камней поддержки нативной компиляции как со стороны Spring Boot, та и со стороны GraalVM.
Читать статью
Teletype
Создаем нативное Kotlin приложение на Spring Boot Native, Gradle и GraalVM без докера под MacOS и Windows
В этой статье я хочу рассказать о практическом опыте нативной компиляции production приложения, написанного на Kotlin со Spring Boot...
Что такое нелокальный return?
В Котлин non-local return — это механизм, который позволяет выйти из внешней функции или лямбда-выражения и вернуться к вызывающему коду, обходя оставшуюся часть текущей функции или лямбда-выражения. Он работает по-разному в зависимости от того, является ли функция inline или не-inline.
В не-inline функциях:
Если внутри функции есть лямбда-выражение, non-local return из лямбда-выражения может привести к нелокальному завершению внешней функции.
Для использования non-local return внутри лямбда-выражения в не-inline функции, необходимо использовать метку (label) и оператор
В inline-функциях:
В inline-функциях, лямбда-выражения становятся частью кода функции и имеют локальный контроль над потоком управления.
Оператор
В Котлин non-local return — это механизм, который позволяет выйти из внешней функции или лямбда-выражения и вернуться к вызывающему коду, обходя оставшуюся часть текущей функции или лямбда-выражения. Он работает по-разному в зависимости от того, является ли функция inline или не-inline.
В не-inline функциях:
Если внутри функции есть лямбда-выражение, non-local return из лямбда-выражения может привести к нелокальному завершению внешней функции.
Для использования non-local return внутри лямбда-выражения в не-inline функции, необходимо использовать метку (label) и оператор
return@label.В inline-функциях:
В inline-функциях, лямбда-выражения становятся частью кода функции и имеют локальный контроль над потоком управления.
Оператор
return внутри лямбда-выражения в inline-функции приведет только к завершению самого лямбда-выражения, не влияя на внешнюю функцию.Реализуем современный UI на Jetpack Compose
Всем привет, на связи Никита Пятаков, Android-разработчик в МТС Диджитал. В этой статье я расскажу вам о том, как в приложении Мой МТС была проведена работа над UI новой карточки услуги. Рассказ мой будет последовательным – сначала про саму задачку, потом про решение, которое разбито на подпункты.
Читать статью
Всем привет, на связи Никита Пятаков, Android-разработчик в МТС Диджитал. В этой статье я расскажу вам о том, как в приложении Мой МТС была проведена работа над UI новой карточки услуги. Рассказ мой будет последовательным – сначала про саму задачку, потом про решение, которое разбито на подпункты.
Читать статью
Teletype
Реализуем современный UI на Jetpack Compose
Всем привет, на связи Никита Пятаков, Android-разработчик в МТС Диджитал. В этой статье я расскажу вам о том, как в приложении Мой МТС...
Как работает модификатор crossinline?
crossinline — ключевое слово, которое используется для указания, что лямбда-выражение не может содержать нелокальных return, даже если оно передано в inline-функцию.
Когда мы передаем лямбда-выражение в функцию в качестве параметра, мы можем использовать оператор return внутри лямбды, чтобы выйти из цикла или функции, в которой вызывается лямбда. Однако, если мы передаем лямбда-выражение в inline-функцию, код лямбда-выражения может быть вставлен прямо в место вызова функции. В этом случае, если в лямбде используется оператор return, это может привести к выходу из внешней функции, что не всегда желательно.
crossinline — ключевое слово, которое используется для указания, что лямбда-выражение не может содержать нелокальных return, даже если оно передано в inline-функцию.
Когда мы передаем лямбда-выражение в функцию в качестве параметра, мы можем использовать оператор return внутри лямбды, чтобы выйти из цикла или функции, в которой вызывается лямбда. Однако, если мы передаем лямбда-выражение в inline-функцию, код лямбда-выражения может быть вставлен прямо в место вызова функции. В этом случае, если в лямбде используется оператор return, это может привести к выходу из внешней функции, что не всегда желательно.
Protobuf или Reflection в JNI
Вы когда нибудь задумывались, на сколько grpc быстрый. Да в сети, ему равных нет. Если вы гоняете маленькие сообщения, которые надо быстро доставить, то лучше grpc попростуне найти ( найти, но по мнению автору protobuf остается движком сериализации, поддерживающим большее кол-во языков ). Но насколько он хорош? Сможет ли он к примеру сравнится просто с нативными вызовами?
Попробуем сравнить это, но так как в обычной жизни нам это может не пригодится, то добавим еще одно условие - сравниваем как лучший способ взаимодействия с jni библиотекой.
Читать статью
Вы когда нибудь задумывались, на сколько grpc быстрый. Да в сети, ему равных нет. Если вы гоняете маленькие сообщения, которые надо быстро доставить, то лучше grpc попросту
Попробуем сравнить это, но так как в обычной жизни нам это может не пригодится, то добавим еще одно условие - сравниваем как лучший способ взаимодействия с jni библиотекой.
Читать статью
Teletype
Protobuf или Reflection в JNI
Вы когда-нибудь задумывались, насколько grpc быстрый. Да, в сети, ему равных нет. Если вы гоняете маленькие сообщения, которые надо...
Когда нужно использовать crossinline, а когда noinline?
Модификаторы crossinline и noinline используются для управления поведением лямбда-выражений, переданных в качестве параметров функций. Они позволяют указывать, может ли лямбда-выражение содержать операторы return.
• Модификатор crossinline используется для указания того, что лямбда-выражение не может содержать операторы return, даже если функция, принимающая лямбда-выражение, инлайновая.
• Модификатор noinline, с другой стороны, указывает на то, что лямбда-выражение может быть сохранено как объект функции, а не выполнено внутри вызывающей функции. Это может быть полезно в случае, когда вы хотите использовать лямбда-выражение где-то ещё, например, как параметр для другой функции.
ВЫВОД: crossinline должен использоваться только тогда, когда вы уверены в том, что оператор return не будет использоваться внутри лямбда-выражения. Если лямбда-выражение должно содержать оператор return, то следует использовать ключевое слово noinline вместо crossinline.
Модификаторы crossinline и noinline используются для управления поведением лямбда-выражений, переданных в качестве параметров функций. Они позволяют указывать, может ли лямбда-выражение содержать операторы return.
• Модификатор crossinline используется для указания того, что лямбда-выражение не может содержать операторы return, даже если функция, принимающая лямбда-выражение, инлайновая.
• Модификатор noinline, с другой стороны, указывает на то, что лямбда-выражение может быть сохранено как объект функции, а не выполнено внутри вызывающей функции. Это может быть полезно в случае, когда вы хотите использовать лямбда-выражение где-то ещё, например, как параметр для другой функции.
ВЫВОД: crossinline должен использоваться только тогда, когда вы уверены в том, что оператор return не будет использоваться внутри лямбда-выражения. Если лямбда-выражение должно содержать оператор return, то следует использовать ключевое слово noinline вместо crossinline.
NoArchitecture Kotlin Compose
Статья про основные моменты использования Compose в Android разработке на примере простого приложения. Три таба в одном Activity. Обращение в сеть, парсинг Json. Немного анимации. Приложение сделано на коленке за пару дней.
Читать статью
Статья про основные моменты использования Compose в Android разработке на примере простого приложения. Три таба в одном Activity. Обращение в сеть, парсинг Json. Немного анимации. Приложение сделано на коленке за пару дней.
Читать статью
Teletype
NoArchitecture Kotlin Compose
Все начинается в setContent. ComposeGenAppTheme необязательна. Surface кстати внутри себя содержит простой Box. Не привычно формировать...
Ключевое слово reified
reified — это ключевое слово, которое может быть использовано только в inline-функциях. reified позволяет получить информацию о типе generic-параметра во время выполнения программы. В обычном случае, информация о типах стирается и недоступна во время выполнения, но с помощью reified можно сохранять эту информацию и использовать в других частях приложения.
Несколько простых примеров применения:
1. Получить доступ к типу параметра во время выполнения
2. reified вместе с is для проверки типа аргумента во время выполнения
3. Получить список элементов перечисления
reified — это ключевое слово, которое может быть использовано только в inline-функциях. reified позволяет получить информацию о типе generic-параметра во время выполнения программы. В обычном случае, информация о типах стирается и недоступна во время выполнения, но с помощью reified можно сохранять эту информацию и использовать в других частях приложения.
Несколько простых примеров применения:
1. Получить доступ к типу параметра во время выполнения
fun main() {
printType<String>() // String
printType<Int>() // Int
}
private inline fun <reified T> printType() {
println(T::class.simpleName)
}
В этом примере мы определяем функцию printType() с типовым параметром T, который мы указываем с помощью reified. Внутри функции мы можем получить тип T во время выполнения, используя T::class. Затем выводим название типа на экран с помощью simpleName. Когда мы вызываем функцию printType() с типом String или Int, она выводит соответствующий тип на экран.2. reified вместе с is для проверки типа аргумента во время выполнения
fun main() {
println(isOfType<Int>(1)) // true
println(isOfType<Int>("Hello")) // false
}
private inline fun <reified T> isOfType(value: Any): Boolean {
return value is T
}
Здесь мы определяем функцию isOfType(), которая принимает значение типа Any и возвращает true, если оно является типом T. Мы используем reified, чтобы получить доступ к типу T во время выполнения. Затем мы используем оператор is для проверки типа значения и возвращаем соответствующее boolean значение.3. Получить список элементов перечисления
enum class Color { RED, GREEN, BLUE }
fun main() {
printEnumValues<Color>() // RED, GREEN, BLUE
}
private inline fun <reified T : Enum<T>> printEnumValues() {
enumValues<T>().forEach { value ->
println(value)
}
}
Определяем функцию printEnumValues(), которая выводит список элементов перечисления типа T. Мы применяем reified, чтобы получить доступ к типу T во время выполнения. Затем используем enumValues<T>(), чтобы получить список всех значений перечисления типа T. Внутри цикла выводим каждое значение на экран. Когда мы вызываем функцию printEnumValues() с типом Color, она выводит "RED", "GREEN" и "BLUE" в консоль.Библиотека Scout — быстрый и безопасный DI на Kotlin
Привет! Меня зовут Александр Миронычев. Я занимаюсь инфраструктурой приложения Яндекс Маркет под Android. Около двух лет назад при работе над модульностью у меня появилось желание написать собственную библиотеку для внедрения зависимостей, которая позволила бы ускорить сборку приложения и упростить процесс модуляризации. Так появился Scout. Сегодня его код мы выложили в открытый доступ.
Эта статья — рассказ о том, как пройти путь от безумной идеи до конкурентоспособного опенсорс-фреймворка. Статья будет полезна тем, кто ищет замену DI-фреймворку в своем проекте, а также тем, кто мечтает написать свою библиотеку, но никак не может начать.
Читать статью
Привет! Меня зовут Александр Миронычев. Я занимаюсь инфраструктурой приложения Яндекс Маркет под Android. Около двух лет назад при работе над модульностью у меня появилось желание написать собственную библиотеку для внедрения зависимостей, которая позволила бы ускорить сборку приложения и упростить процесс модуляризации. Так появился Scout. Сегодня его код мы выложили в открытый доступ.
Эта статья — рассказ о том, как пройти путь от безумной идеи до конкурентоспособного опенсорс-фреймворка. Статья будет полезна тем, кто ищет замену DI-фреймворку в своем проекте, а также тем, кто мечтает написать свою библиотеку, но никак не может начать.
Читать статью
Teletype
Библиотека Scout — быстрый и безопасный DI на Kotlin
Привет! Меня зовут Александр Миронычев. Я занимаюсь инфраструктурой приложения Яндекс Маркет под Android. Около двух лет назад при...
Почему reified возможно использовать только с inline-функциями?
Ключевое слово reified используется только с inline-функциями, т.к. оно позволяет получить доступ к информации о типе-параметре на этапе выполнения программы, что невозможно для обычных (non-inline) функций.
inline-функции в Kotlin позволяют копировать тело функции непосредственно в вызывающий код. Это позволяет избежать накладных расходов на создание объектов и вызовы функций при каждом вызове.
Именно reified в комбинации с inline позволяет сохранить информацию о типе-параметре и передать ее внутрь функции в рантайме, что было бы невозможно без inline.
Также стоит отметить, что ключевое слово reified можно применять только с обобщенными типами (дженериками).
Ключевое слово reified используется только с inline-функциями, т.к. оно позволяет получить доступ к информации о типе-параметре на этапе выполнения программы, что невозможно для обычных (non-inline) функций.
inline-функции в Kotlin позволяют копировать тело функции непосредственно в вызывающий код. Это позволяет избежать накладных расходов на создание объектов и вызовы функций при каждом вызове.
Именно reified в комбинации с inline позволяет сохранить информацию о типе-параметре и передать ее внутрь функции в рантайме, что было бы невозможно без inline.
Также стоит отметить, что ключевое слово reified можно применять только с обобщенными типами (дженериками).
Почему reified можно использовать только с обобщенными типами (generics)?
Ключевое слово reified в языке Kotlin можно использовать только с обобщенными типами, потому что оно предназначено для решения конкретной проблемы, связанной именно с дженериками.
Одна из особенностей обобщенных типов заключается в том, что информация о типе становится недоступной на этапе выполнения программы. Вместо этого на этапе компиляции создается код, который работает с типом-параметром "на уровне объекта", то есть как с любым другим объектом, не зная его конкретного типа.
Именно reified позволяет сохранить информацию о типе-параметре на этапе выполнения программы. И дает нам возможность проверять типы в рантайме, создавать объекты типа-параметра и передавать их в качестве параметров других функций.
Таким образом, ключевое слово reified не имеет смысла применять к необобщенным типам, поскольку они уже доступны в качестве конкретных объектов на этапе выполнения.
Ключевое слово reified в языке Kotlin можно использовать только с обобщенными типами, потому что оно предназначено для решения конкретной проблемы, связанной именно с дженериками.
Одна из особенностей обобщенных типов заключается в том, что информация о типе становится недоступной на этапе выполнения программы. Вместо этого на этапе компиляции создается код, который работает с типом-параметром "на уровне объекта", то есть как с любым другим объектом, не зная его конкретного типа.
Именно reified позволяет сохранить информацию о типе-параметре на этапе выполнения программы. И дает нам возможность проверять типы в рантайме, создавать объекты типа-параметра и передавать их в качестве параметров других функций.
Таким образом, ключевое слово reified не имеет смысла применять к необобщенным типам, поскольку они уже доступны в качестве конкретных объектов на этапе выполнения.
Почему нельзя все функции сделать inline?
Технически, можно попробовать сделать все функции inline. Однако, это может привести к ряду негативных последствий:
1. Увеличение размера скомпилированного кода
Поскольку inline-функции заменяются на их вызовы во время компиляции, это может привести к увеличению размера скомпилированного кода, особенно если функции содержат большой объем кода.
2. Увеличение времени компиляции
inline-функции могут увеличить время компиляции проекта, так как компилятору нужно заменить каждый вызов функции на ее код.
3. Увеличение расхода памяти
Если функции являются часто используемыми и содержат большой объем кода, использование inline-функций может привести к увеличению расхода памяти.
4. Ограничения на использование лямбда-выражений
Применение inline-функций может ограничить возможности использования лямбда-выражений. Например, в inline-функциях нельзя использовать функции, которые не могут быть inlined, такие как protected-функции или функции из других модулей.
5. Ограничения на использование рекурсии
Использование inline-функций может ограничить возможность использования рекурсии, так как замена рекурсивного вызова функции на ее код может привести к бесконечной рекурсии или переполнению стека.
ВЫВОД: если все функции сделать inline, это может привести к экспоненциальному росту размера кода и увеличению времени компиляции. Поэтому необходимо выбирать оптимальную стратегию для каждой конкретной функции в зависимости от ее предполагаемого использования.
Технически, можно попробовать сделать все функции inline. Однако, это может привести к ряду негативных последствий:
1. Увеличение размера скомпилированного кода
Поскольку inline-функции заменяются на их вызовы во время компиляции, это может привести к увеличению размера скомпилированного кода, особенно если функции содержат большой объем кода.
2. Увеличение времени компиляции
inline-функции могут увеличить время компиляции проекта, так как компилятору нужно заменить каждый вызов функции на ее код.
3. Увеличение расхода памяти
Если функции являются часто используемыми и содержат большой объем кода, использование inline-функций может привести к увеличению расхода памяти.
4. Ограничения на использование лямбда-выражений
Применение inline-функций может ограничить возможности использования лямбда-выражений. Например, в inline-функциях нельзя использовать функции, которые не могут быть inlined, такие как protected-функции или функции из других модулей.
5. Ограничения на использование рекурсии
Использование inline-функций может ограничить возможность использования рекурсии, так как замена рекурсивного вызова функции на ее код может привести к бесконечной рекурсии или переполнению стека.
ВЫВОД: если все функции сделать inline, это может привести к экспоненциальному росту размера кода и увеличению времени компиляции. Поэтому необходимо выбирать оптимальную стратегию для каждой конкретной функции в зависимости от ее предполагаемого использования.
Философия Compose
Всем привет! Недавно я начала изучать Jetpack Compose. Всё, что я изучаю по иностранным гайдам, я обычно перевожу, чтобы при повторном прочтении, мозг снова не тратил время на перевод. Мне кажется, этот фреймворк становится всё более популярен, поэтому хочу поделиться своим переводом Thinking in Compose с другими начинающими :)
Jetpack Compose — это современный декларативный UI Toolkit для Android, упрощающий написание и поддержку UI (пользовательского интерфейса) вашего приложения, и в этом гайде рассказывается за счёт чего это достигается.
Читать статью
Всем привет! Недавно я начала изучать Jetpack Compose. Всё, что я изучаю по иностранным гайдам, я обычно перевожу, чтобы при повторном прочтении, мозг снова не тратил время на перевод. Мне кажется, этот фреймворк становится всё более популярен, поэтому хочу поделиться своим переводом Thinking in Compose с другими начинающими :)
Jetpack Compose — это современный декларативный UI Toolkit для Android, упрощающий написание и поддержку UI (пользовательского интерфейса) вашего приложения, и в этом гайде рассказывается за счёт чего это достигается.
Читать статью
Teletype
Философия Compose
Всем привет! Недавно я начала изучать Jetpack Compose. Всё, что я изучаю по иностранным гайдам, я обычно перевожу, чтобы при повторном...
Реализация экранов авторизации и регистрации с помощью Custom View и Firebase
Каждый из нас сталкивается с авторизацией и регистрацией в приложениях как пользователь и как разработчик. Но перед разработчиком стоит более важная задача, а именно реализовать View таким образом, чтобы данные, которые введет пользователь, были корректно обработаны и переданы на сервер, что если пользователь введет вместо своего email просто набор символов, или напишет пароль из одной цифры? В нормальных приложениях это недопустимо! В этой статье я хочу продемонстрировать демо приложение, где будет представлен способ обработки данных полей с использованием Custom View и авторизацией в firebase.
Читать статью
Каждый из нас сталкивается с авторизацией и регистрацией в приложениях как пользователь и как разработчик. Но перед разработчиком стоит более важная задача, а именно реализовать View таким образом, чтобы данные, которые введет пользователь, были корректно обработаны и переданы на сервер, что если пользователь введет вместо своего email просто набор символов, или напишет пароль из одной цифры? В нормальных приложениях это недопустимо! В этой статье я хочу продемонстрировать демо приложение, где будет представлен способ обработки данных полей с использованием Custom View и авторизацией в firebase.
Читать статью
Teletype
Реализация экранов авторизации и регистрации с помощью Custom View и Firebase
Каждый из нас сталкивается с авторизацией и регистрацией в приложениях как пользователь и как разработчик. Но перед разработчиком стоит...