Как стать автором
Обновить
47.36

Kotlin *

Статически типизированный язык программирования

Сначала показывать
Порог рейтинга

Добавлен Room! :)
Ранее я уже делился статьей про Delight SQL Viewer — библиотеку, позволяющую отлаживать SQLDelight-базу данных напрямую внутри вашего Kotlin Multiplatform-приложения. Однако в одном из наших внутренних проектов используется Room Multiplatform и хотелось иметь возможность отладки БД и в нем. Так и появилась вторая версия библиотеки, которая теперь поддерживает и Room, и SQLDelight.

Что делает библиотека?

  • Позволяет просматривать, добавлять, редактировать и удалять записи в базе через удобный UI прямо в приложении.

  • Автоматически добавляет иконку-ярлык для быстрого запуска (Android и iOS).

  • На Desktop ярлыки не поддерживаются. Для запуска интерфейса используйте обычную кнопку или меню в вашем UI.

  • Легко отключается в продакшен-сборках — можно либо не вызывать init, либо подключать stub-модуль вместо основной библиотеки.

Как использовать?

Зависимости (shared/build.gradle.kts)

val isRelease = /* Ваша логика определения релизной сборки */

dependencies {
    if (isRelease) {
        // В релизе – stub, чтобы не вшивать весь отладочный UI.
        api("ru.bartwell.delightsqlviewer:stub:2.0.0")
    } else {
        // В debug – полная функциональность.
        api("ru.bartwell.delightsqlviewer:runtime:2.0.0")
        api("ru.bartwell.delightsqlviewer:core:2.0.0")
        // Выберите, что используете:
        api("ru.bartwell.delightsqlviewer:sqldelight-adapter:2.0.0")
        // или
        // api("ru.bartwell.delightsqlviewer:room-adapter:2.0.0")
    }
}

Инициализация

  • SQLDelight (Android):

    DelightSqlViewer.init(
        object : SqlDelightEnvironmentProvider() {
            override fun getDriver() = sqlDelightDriver
            override fun getContext() = context
        }
    )
  • Room (Android):

    DelightSqlViewer.init(
        object : RoomEnvironmentProvider() {
            override fun getDriver() = roomDatabase
            override fun getContext() = context
        }
    )
  • iOS (пример для SQLDelight):

    let provider = SqlDelightEnvironmentProvider(driver: sqlDriver)
    DelightSqlViewer.shared.doInit(provider: provider, isShortcutEnabled: true)

    Аналогично и для RoomEnvironmentProvider.

    Также, чтобы ярлык корректно работал на iOS, в вашем AppDelegate нужно переопределить методы обработки ярлыков, например:

    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(
            _ application: UIApplication,
            configurationForConnecting connectingSceneSession: UISceneSession,
            options: UIScene.ConnectionOptions
        ) -> UISceneConfiguration {
            return ShortcutActionHandler.shared.getConfiguration(session: connectingSceneSession)
        }
    }

    Или вызовите DelightSqlViewer.shared.launch() в обработчике вашего Shortcut.

  • Desktop:

    DelightSqlViewer.init(
        object : SqlDelightEnvironmentProvider() {
            override fun getDriver() = sqlDelightDriver
        }
    )

Аналогично и для RoomEnvironmentProvider.

Запуск

После инициализации вызов DelightSqlViewer.launch() откроет интерфейс просмотра и редактирования (на Android/iOS можно также запустить через ярлык при долгом тапе на иконку приложения).

Button(onClick = { DelightSqlViewer.launch() }) {
    Text("Open DB Viewer")
}

Итог

Теперь Delight SQL Viewer покрывает оба основных способа хранения данных в мультиплатформенных проектах — SQLDelight и Room Multiplatform. Если нужно быстро проверить содержимое вашей БД или вручную поправить что-то прямо во время тестирования, эта библиотека может сэкономить кучу времени. Ну и, конечно, легко «прячется» в релизе, чтобы никакого отладочного UI не оставалось.

Ссылка на репозиторий: https://github.com/bartwell/delight-sql-viewer

Буду рад фидбэку и вопросам!

Теги:
+3
Комментарии0

Kotlin Multiplatform на практике: как работать с технологией (видео-туториал)

Выпустили серию видео о базовых аспектах работы с Kotlin Multiplatform, технологией для мультиплатформенной разработки (iOS, Android, Web, Desktop).

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

Рассказали, как и для чего применять технологию на практике, и как к ней подступиться.

Уже доступны все шесть выпусков туториала:

1. Что из себя представляет технология KMP?

2. Настройка окружения

3. Структура проекта

4. Верстка на SwiftUI

5. Верстка на Compose

6. Сетевой слой

Посмотреть туториал можно здесь:

К каждому выпуску приложен документ с пояснением некоторых терминов и полезными ссылками (см. в описании видео), которые пригодятся при ознакомлении с материалом.

Теги:
Всего голосов 9: ↑9 и ↓0+9
Комментарии0

Привет, друзья! Меня зовут Александр Минкин, в компании SM Lab я работаю тимлидом Android-разработки на продукте МП Спортмастер. Сегодня я хочу поделиться с вами подробностями об одном из самых мощных архитектурных паттернов для мобильных приложений - MVI (Model-View-Intent). Этот паттерн помогает создавать приложения с четко разделенной логикой, улучшенной тестируемостью и высокой масштабируемостью. Давайте разберемся в его особенностях и посмотрим примеры кода на языке программирования Kotlin в Android с использованием Kotlin Coroutines, StateFlow и Fragment, а также давайте расширим наш пример с использованием чистой архитектуры, где добавим уровни domain-слоя (UseCases) и data-слоя (Repository). Этот подход поможет вам управлять состояниями приложения более эффективно и реагировать на изменения в реальном времени.

 Основные компоненты MVI с чистой архитектурой:

1. Model: Хранит состояние приложения.

2. View: Отображает текущее состояние Model.

3. Intent: Интерпретирует действия пользователя и направляет их в UseCase.

4. UseCase: Содержит бизнес-логику и выполняет операции.

5. Repository: Обеспечивает доступ к данным, будь то локальные или удаленные источники.

Преимущества MVI:

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

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

- Тестируемость: Изолированные компоненты упрощают написание тестов.

Давайте рассмотрим пример использования MVI в приложении на Kotlin. Допустим, у нас есть приложение для управления задачами. Ссылка на gist:

https://gist.github.com/Rasalexman/53f9be0fc4e295b987e0921839a9a84e

Здесь мы рассмотрели базовый пример использования MVI. Хочу отметить, что в разных реализациях этот архитектурный паттерн, может включать в себя несколько дополнительных компонентов, таких как Reducer - это компонент помогающий преобразовать входное намерение в состояние. В примере выше таким reducer может выступать функция `processIntent`, но чаще его делают как абстракцию в виде интерфейса с функцией reduce, которая принимает Intent и возвращает State. Также мы можем добавить такой компонент как Store - это общая часть для работы с намерениями, которая получает результат обработки намерения и может производить как SideEffects, так и само состояние (State) экрана. Количество компонентов может меняться от сложности реализации, вплоть до добавления специальных объектов middleware и сайд-эффектов (SideEffects). Подробное рассмотрение данных компонентов не входило в текущую статью. С более сложными реализациями вы можете ознакомиться по ссылкам ниже

Заключение:

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

Использование Kotlin Coroutines и StateFlow с архитектурой MVI позволяет вам эффективно управлять состояниями и асинхронными операциями в вашем приложении. Интеграция чистой архитектуры с использованием UseCases и Repository делает ваше приложение более модульным и легко масштабируемым. Это упрощает написание кода, при этом ваше приложение становится более отзывчивым и масштабируемым, а так же удобным в управлении данными и бизнес-логикой, улучшая тестируемость и поддержку кода.

Спасибо, что прочитали данную статью. Буду признателен за комментарии и реакции к этому посту. Делить какую реализацию MVI вы используете у себя в проектах. Всем отличного настроения, помните, что его, как и архитектуру, вы можете выбирать сами ;)

Теги:
Всего голосов 2: ↑1 и ↓10
Комментарии0

Вклад инженеров Axiom JDK в развитие OpenIDE

На текущий момент среди разработчиков Java в качестве основной среды разработки применяется IntelliJ IDEA. Однако, коммерческая версия этого и других продуктов JetBrains, включая IDE, Code With Me, Upsource, TeamCity и Space, а также техническая поддержка теперь не доступны в России. Это побудило нас на создание продукта OpenIDE с открытым исходным кодом и всей инфраструктурой, размещенной на территории РФ.

Как было анонсировано ранее, OpenIDE создается на базе исходного кода IntelliJ IDEA CE и будет развиваться в рамках некоммерческого партнерства Axiom JDK, «Группы Астра» и Haulmont. В этом посте мы расскажем о вкладе команды Axiom JDK в проект.

Рантайм Axiom JDK будет предоставляться в качестве выбора по умолчанию для разработки на Java/Kotlin в OpenIDE. Дополнительно будет возможна установка Axiom JDK из интерфейса OpenIDE. При этом релизный цикл Axiom JDK синхронизирован с OpenJDK и регулярными обновлениями.

Команда Axiom JDK будет выпускать и поддерживать рантайм, используемый для запуска OpenIDE, с набором улучшений. Это, например, расширенное переопределение классов c помощью DCEVM и поддержка JCEF фреймворка для встраивания браузера на базе Chromium. Также планируется ряд улучшений для рендеринга шрифтов, поддержка режимов HiDPI, что обеспечит лучшее масштабирование интерфейса пользователя. А еще это позволит исправлять специфичные для работы IDE ошибки, исправлений для которых еще нет в OpenJDK.

Несмотря на то, что исходный код IntelliJ IDEA CE открыт, в процессе работы IDEA обращается к серверам JetBrains для обновлений, поддержки маркетплейса плагинов, а также других нужд. Этот функционал сейчас перерабатывается с участием инженеров Axiom JDK, что позволит создать локальную российскую библиотеку плагинов, локализованный (и отключаемый) сбор статистики и механизм обновления OpenIDE.

Наконец, команда Axiom JDK занимается настройкой сборочного конвейера OpenIDE, и со временем произведет анализ всех OSS зависимостей OpenIDE и будет обеспечивать оперативное исправлений уязвимостей в ОSS зависимостях в рамках релизного цикла OpenIDE.

Релиз продукта намечен на март 2025 года.

Axiom JDK — единственный российский разработчик JDK. Инженеры команды стояли у истоков Java в России и развивают платформу более 25 лет.

OpenIDE можно использовать взамен IntelliJ IDEA CE. По данным нашего исследования, 78% Java разработчиков используют IntelliJ IDEA Ultimate, а 47% - работают на Community Edition. Мы хотим предоставить сотням тысяч разработчиков открытый инструмент, не уступающий по удобству привычным IDE, чтобы они могли быстро и эффективно работать.

Читайте также у нас на сайте и у партнеров на хабре.

Теги:
Всего голосов 5: ↑5 и ↓0+5
Комментарии0

Привет, Хабр!

В октябре на конференции Joker мы представили EAP версию Explyt Test, плагина для IntelliJ IDEA Community, который умеет генерировать тесты на базе AI и формальных методов. Мы получили много интересных и, временами, неожиданных комментариев от участников о том, что они ждут от автоматической генерации тестов и способен ли им в этом помочь AI.

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

  • поддержана совместимость с IntelliJ IDEA 2024.3 и K2 для IntelliJ IDEA 2024.2+

  • добавлен AI ассистент Explyt Chat, который умеет объяснять код, находить в нем ошибки, поддерживает вложения и отвечает на любые вопросы пользователя

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

  • добавлена возможность управления выбором примера тестов при генерации и ввода дополнительных промптов

  • добавлен анализ эффективности Ollama моделей: модели низкого качества помечаются как нерекомендуемые (not recommended)

  • оптимизированы алгоритмы сбора контекста приложения, установки зависимостей, разрешения неоднозначных импортов при автоматизированном применении квикфиксов

  • поддержана совместимость с Android Studio Koala и Android Studio Ladybug (часть функциональности)

Генерация тестов:

  1. Генерация Gherkin сценариев и тестов по исходному коду

  2. Генерация дополнительных тестов с учётом существующего покрытия

  3. Исправление тестов: обеспечиваем их компилируемость и корректное выполнение

  4. Управление генерацией: выбор примеров и задание дополнительных инструкций для языковой модели, редактирование сгенерированных сценариев и создание собственных 

  5. Подготовка проекта к генерации тестов: поиск используемых тестовых фреймворков, установка дополнительных зависимостей при необходимости

AI ассистент Explyt Chat:

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

  2. Объяснение работы кода и нюансов его использования. Action: Explain Code

  3. Анализ кода на предмет потенциальных ошибок в реализации. Action: Analyze for Bugs

Пользователи могут обращаться к языковым моделям как через серверы Explyt, так и с использованием собственных API-ключей. Поддерживаются модели от различных провайдеров (OpenAI, DeepSeek и др.), а также возможно использование локальных моделей Ollama.

Скачать плагин можно на сайте, для багрепортов и фичреквестов – GitHub Issues, для новостей и общения – телеграм.

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

Теги:
Всего голосов 13: ↑13 и ↓0+18
Комментарии0

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

Теги:
Рейтинг0
Комментарии0

Чебурашка

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

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

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

Пересылать фото банкомата в секретных чатах? Это не путь настоящего обнальщика.

Схема такая: Сервер для обмена видео по RSTP + Фельдману и Шило по Android телефону, где отправителю денег предаётся видео через эмулирование камеры с камеры получателя.

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

MVP проекта (вход рубль - выход десять лет по 7 части статьи 159 УК РФ)

Теги:
Всего голосов 6: ↑4 и ↓2+5
Комментарии1

Прошлый мой пост снискал некоторую солидарность, так что имеет смысл написать, что же делать, чтобы починить IDEA/gradle.

Итак, если у вас что-то ошибочно красится красным в IDE, у нас есть все этапы принятия (Отрицание и Гнев можно менять местами):

  1. Отрицание

    1. File -> Invalidate caches... -> Clear file system cache and Local History (опционально отметить галочкой ClearVCS Log caches and indexes, мне иногда почему-то помогало)

    2. Перезагружаем, ждём градл индекса, потенциально - продолжаем гореть

  2. Гнев

    1. Пробуем почистить проект через ./gradlew clean

    2. Пробуем собрать через ./gradlew build

  3. Торг - Тут обычно есть два варианта: оно собралось во время Гнева или нет. Если нет - пропускаем второй подпункт

    1. Удаляем контент по пути ~/.m2/repository

    2. goto Отрицание

  4. Депрессия

    1. НЕ ТРОГАЕМ ~/.gradle/gradle.properties . Удаляем контент по пути ~/.gradle/ . Я обычно это делаю через файловый менеджер - выделить всё, развыделить gradle.properties, shift+delete

    2. goto Отрицание

  5. Принятие

    1. Можно переустановить систему, но может не помочь

    2. Лучше проделоть все предыдущие шаги (а вдруг второй раз поможет)

    3. Переклонировать проект (не забудьте закоммитить изменения)

    4. Переустановить IDE (2024.1.6 на данный момент относительно нормально работает, можно даже новый UI выключить) (желательно тогда ещё конфиги и кэши версий удалить, но сами понимаете - потом надо будет ковырять настройки и скачивать IDE)

Другого рецепта счастья у меня для вас сейчас нет, искренне желаю продуктивной работы на фоне стабильных IDE и систем сборки :)

Теги:
Всего голосов 3: ↑2 и ↓1+3
Комментарии2

Мы в компании все проекты, какие возможно, пишем на Kotlin. Я всем сердцем его люблю. Оттого больнее то, что с ним происходит...

Сегодня утром мне написал коллега. Говорит, помоги разобраться:

renderConstructor mustn't be called with an intersection type argument. Call render to simply render the type or filter out intersection types on the call-site.

Решилось какой-то там пересборкой, возможно, какой-то очисткой кэша. Казалось бы, ну мы же инженеры, почему у нас "какая-то пересборка" и "возможно"? Вот в этом и проблема.

Примерно с год-два я наблюдаю, как в котлине творятся проблемы с:

  • Надёжностью сборок. То тут, то там какие-то приколы со странными ошибками, которые то есть, то нет

  • Тулингом. Постоянные косяки в подсветке в IDE, отсутствие удобных визардов для создания проектов, особенно для проектов вроде на базе Kotlin Multiplatform

  • Библиотеками. Не все базовые вещи закрыты (привет, kotlinx-io без поддержки файлов в JS Browser), Compose Multiplatform пытается сделаться кроссплатформенным (привет, Compose Web, который не использует нативные HTML тэги и CSS стили)

Я понимаю, что сейчас происходит переход на K2 (не все библиотеки на него перешли => вскрываются новые проблемы время от времени). Я понимаю, что язык и его рабочее окружение пытается двигаться. Но я не понимаю, почему я не могу запустить gradlew clean build и не бояться, что какие-то кэши сборки затрутся во время этой же сборки.

Я надеюсь, что котлин будет становиться лучше. Но я пока не понимаю, когда.

Теги:
Всего голосов 4: ↑4 и ↓0+7
Комментарии2

Мы создали свой инструмент для доставки сборок Android-приложений

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

Да, мы могли бы пользоваться Firebase App Distribution с помощью VPN, но это не очень удобно. VPN-сервисы ненадежны, потому что подвержены блокировкам. К тому же создание собственного решения позволяет добавлять новые функции и адаптировать инструмент под конкретные нужды команды.

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

Для его реализации выбрали фреймворк Ktor. Благодаря этому любой разработчик, знакомый с Kotlin, сможет быстро разобраться в кодовой базе, поддерживать инструмент и интегрировать его с различными проектами. А в качестве интерфейса решили выбрать Telegram. Наши рабочие чаты чаще всего находятся именно там. Кроме того, Telegram Bot API предоставляет много возможностей, хоть и имеет некоторые ограничения.

Делимся исходным кодом этого инструмента. А подробная инструкция по работе с ним — в отдельной статье.

Теги:
Всего голосов 5: ↑5 и ↓0+7
Комментарии0

В scala 3 есть свои context receivers и они не похожи на то что есть в Kotlin!

object PostConditions:
  opaque type WrappedResult[T] = T

  def result[T](using r: WrappedResult[T]): T = r

  extension [T](x: T)
    def ensuring(condition: WrappedResult[T] ?=> Boolean): T =
      assert(condition(using x))
      x
end PostConditions
import PostConditions.{ensuring, result}

val s = List(1, 2, 3).sum.ensuring(result == 6)

Разберу по строчкам:

opaque type WrappedResult[T] = T: непрозрачный тип. Внутри объекта PostConditions компилятор "знает" что это один и тот же тип, снаружи смотрит на них как на два разных типа. Это не даст перепутать тип с типом обёртки, и, например, случайно присвоить одно в другое.

def result[T](using r: WrappedResult[T]): T = r: функция, которая принимает неявный параметр откуда-то из контекста и возвращает его как нормальное значение.

extension [T](x: T):
def ensuring(condition: WrappedResult[T] ?=> Boolean): T = ....
extension метод, который принимает лямбду. Лямбда принимает неявный параметр, а метод ensuring его предоставляет.

val s = List(1, 2, 3).sum.ensuring(result == 6)Метод списка sum возвращает Int, для него вызывается вышенаписанный метод ensuring, в который передаётся лямба. внутри лямбды есть неявный параметр и потому там (и только там, больше нигде) можно вызвать функцию result, которая вернёт этот самый T.

В коде где-либо снаружи PostConditions объект типа WrappedResult[T] не получится создать.

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

Мнение: почему мультиплатформа Kotlin не приживется в мире разработки

Спойлер: из-за нелюбви к изменениям и дефицита специалистов.

Наш руководитель направления Flutter и iOS Саша Ворожищев делится основными тезисами статьи о судьбе Kotlin Multiplatform Mobile (KMM). Автор статьи — разработчик Донн Фелкер (Donn Felker) — не пророчит KMM мировой славы. И вот почему.

  • Люди не любят что-то менять. Особенно программисты. Редко встретишь iOS-разработчика, который перешел на Android. И наоборот.

  • Кросс-платформа чаще не оправдывает надежд. Мы уже не раз наблюдали попытки создать кросс-платформенные суперхиты — взять к примеру Flash и ActionScript, Mono и Xamarin, —  но ни одна из этих технологий так и не покорила мир программирования.

Сейчас конкуренцию КММ может составить только Flutter. Пока это лучшее кросс-платформенное решение.

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

  • Универсальность != эффективность. Здесь стоит повторить, как важно подбирать правильные инструменты для решения конкретных задач. Мультиплатформа не может быть панацеей для всех проблем.

Полную версию статьи читайте тут.

А больше про технологии и разработку найдете в телеграм-канале Саши. Приходите, там интересно :)

Теги:
Всего голосов 7: ↑7 и ↓0+7
Комментарии0

Таймер на LaunchedEffect в Compose

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

Причем в лямбде будет находится coroutine context

@Composable
fun Timer() {
    var seconds by remember { mutableStateOf(0) }

    LaunchedEffect(seconds) {
            delay(1000)
            seconds++
        }

    Text(text = "Seconds: $seconds")
}

mutableStateOf - Создает State при изменении которого compose функция перезапускается

remember - сохраняет этот State при каждом перезапуске функции

remember + mutableStateOf

Теги:
Рейтинг0
Комментарии0

Ближайшие события

4 – 5 апреля
Геймтон «DatsCity»
Онлайн
8 апреля
Конференция TEAMLY WORK MANAGEMENT 2025
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань
20 – 22 июня
Летняя айти-тусовка Summer Merge
Ульяновская область

Можно ли организовать свое собственное расширение в Kotlin? Это можно сделать через Delegate

class MyString {
    fun myPrint(text: String) {
        println(text)
    }
}

Есть класс MyString с методом myPrint(). Допустим нам надо сделать собственное расширение printRealExt() без использование встроенных в Kotlin возможностей

fun MyString.printRealExt(text: String) {
    println(text)
}

Реализуем интерфейс и класс с нашим методом "расширения"

interface ExtensionPrint {
    fun printExt(text: String)
}

class ExtensionPrintImpl : ExtensionPrint {
    override fun printExt(text: String) {
        println(text)
    }
}

А затем воспользовавшись Delegation делегируем этот метод

class MyString : ExtensionPrint by ExtensionPrintImpl() {
    fun myPrint(text: String) {
        println(text)
    }
}

Синтаксис вызова из расширения и из делегата выглядит одинаково

    val myString = MyString()
    myString.printRealExt("Real ext")
    myString.printExt("Text from ext")

Таким же образом можно организовать множественное наследование в  Kotlin

interface OneClassInterface {
    fun someOne()
}

class OneClassImpl : OneClassInterface {
    override fun someOne() {
        println("some One")
    }
}

interface TwoClassInterface {
    fun someTwo()
}

class TwoClassImpl : TwoClassInterface {
    override fun someTwo() {
        println("someTwo")
    }
}

class DerivedClass : OneClassInterface by OneClassImpl(), TwoClassInterface by TwoClassImpl()

Есть другие способы?

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии0