W
We Love Android
@we_love_android602 подп.
955просмотров
12 апреля 2024 г.
storyScore: 1.1K
Я веду бэклог постов и в рубрике #насмотренность следующий пост должен был быть про функции-конструкторы. Но иногда нужно просто немного подождать и кто-то сделает все за тебя :) На хабре вышла статья "Конструкторы-самозванцы в Kotlin", где автор описывает варианты мимикрии функций под синтаксис конструктора и в каких случаях это может понадобиться. Спасибо ему! Мне остаётся только досыпать примеров использования в Open Source. 1️⃣ Функция-конструктор Это просто функция высшего порядка, написаная с большой буквы, которая внутри создаёт и возвращает инстанс класса. Полезно, если хочется дать возможность "создавать инстанс интерфейса". Объявляете интерфейс, кладёте рядом с ним функцию с таким же названием и готово, даже импортировать её отдельно не придётся. Реализация интерфейса при этом может остаться приватной. Вызовы MutableStateFlow и MutableSharedFlow в корутинах, Json в kotlinx.serialization это всё вызовы таких функций. Это помогает уменьшить API-surface, а значит упростить использование API. Ещё один вариант использования — вместе с inline-классами. Например, у Size в Compose конструктор помечен как internal, а "создание инстанса" происходит через функцию c двумя параметрами. 2️⃣ Перегрузка Companion.invoke Причины применения указанные в статье (контроль над созданием объекта, создание пула объектов, кэширование и т.д.) классные, но нужны примеры. Пример контроля над созданием объекта можно увидеть в PlatformVersion в ktor. То есть в зависимости от определённой логики мы можем мы либо создаём инстанс, либо возвращаем какой-то существующий. Но часто применение более банальное — вместо вторичного конструктора. Тут я могу только догадываться почему не используется вторичный конструктор, но примеры такого применения можно увидеть в RuleSet из detekt и MockEngine из ktor. Иногда применение вместо вторичного конструктора можно оправдать тем, что логики для подготовки параметров конструктора очень много. Например в SpriteAnimation из korge (игровой движок на Kotlin). 3️⃣ <Context>.invoke() То же самое, что предыдущий вариант, но для случая когда нужно ограничить применение invoke контекстом. В дикой природе этот вариант я не встречал, но сам автор даёт пример применения в yatagan и рассказывает в статье зачем это понадобилось. После выхода context parameters (следующая итерация context receiver'ов) этот вариант будет выглядеть приятнее. 🤔 Как относиться к такому? Я часто вижу хейт в сторону подобных конструкций, мол мимикрия и переопределение операторов это зло, так как порождает неявность. Да, на самом деле вызывается не конструктор, а функция, но что в этом плохого если она выполняет ту же смысловую нагрузку? Уверен, многие с чистой совестью вызывают MutableStateFlow и им не важно, что под капотом. Главное следовать принципу наименьшего удивления. Если что-то выглядит как конструктор, оно и работать должно как конструктор. Накидайте аргументов если я не прав! #kotlin
955
просмотров
2930
символов
Да
эмодзи
Нет
медиа

Другие посты @we_love_android

Все посты канала →
Я веду бэклог постов и в рубрике #насмотренность следующий п — @we_love_android | PostSniper