M
Mobile VK Hub
@mobilehubvk749 подп.
193просмотров
25.8%от подписчиков
26 марта 2026 г.
📷 ФотоScore: 212
expect/actual в KMP: где граница и почему её легко провести не там Kotlin Multiplatform делит код на общий (commonMain) и платформенный (androidMain, iosMain). Граница между ними — механизм expect/actual. В commonMain объявляешь expect-декларацию, в каждом платформенном модуле пишешь actual-реализацию. // commonMain expect fun currentTimeMillis(): Long // androidMain actual fun currentTimeMillis(): Long = System.currentTimeMillis() // iosMain actual fun currentTimeMillis(): Long = (NSDate().timeIntervalSince1970 * 1000).toLong() Выглядит просто, но на практике большинство проблем в KMP-проектах появляется именно здесь, когда expect/actual используют не по назначению. Самая классическая ошибка — выносить через expect/actual слишком много. Видишь, что на Android и iOS нужна работа с файлами, и пишешь: // commonMain expect class FileStorage { fun save(name: String, data: ByteArray) fun load(name: String): ByteArray? fun delete(name: String) } Теперь есть два класса с разной реализацией, которые нужно синхронно поддерживать. Добавил метод — поправил в двух местах. Поменял сигнатуру — снова в двух. А логика вызова FileStorage в бизнес-коде всё равно одинаковая на обеих платформах. Правильный подход: expect/actual только для минимального платформенного примитива, всё остальное — общий код поверх него. // commonMain -- только то, что реально различается expect fun platformFilesDir(): String // commonMain -- вся логика общая class FileStorage { fun save(name: String, data: ByteArray) { val path = "${platformFilesDir()}/$name" // запись через общий API } } На iOS platformFilesDir() вернёт путь через NSFileManager, а на Android через context.filesDir. Второй частый антипаттерн — expect class вместо expect fun. Класс через expect/actual означает две отдельные реализации с разным внутренним состоянием. Это сложнее тестировать и сложнее рефакторить. Функция или интерфейс с actual-фабрикой почти всегда выглядт чище. // commonMain expect fun createHttpClient(): HttpClient // androidMain actual fun createHttpClient() = HttpClient(Android) { ... } // iosMain actual fun createHttpClient() = HttpClient(Darwin) { ... } Хорошее правило: если в expect-декларации больше одного метода, скорее всего, её можно разбить на несколько маленьких expect fun и вынести общую логику в commonMain. Граница expect/actual должна быть как можно у́же. #mobilevk #android #ios #kotlin #kmp
193
просмотров
2465
символов
Нет
эмодзи
Да
медиа

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

Все посты канала →
expect/actual в KMP: где граница и почему её легко провести — @mobilehubvk | PostSniper