TGViewer
Everlasting Loops Everlasting Loops @loops_everlasting · 565 subscribers
Post #11 1K
public class String

Вы могли видеть такую функцию:


public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}


Или такую:


public inline fun <T> mutableListOf(): MutableList<T> = ArrayList()


Что у них общего? Они обе на котлине, и обе объявлены с модификатором public

🤔 Зачем это нужно в лаконичном языке, где сущности и так public по умолчанию?

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

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

Кстати, про то, как никому ничего не сломать, на днях был доклад у @dolgo_polo_dev. И там на секции вопросов подняли тему, что делать, если у нас несколько модулей

Тут нет идеального варианта даже внутри котлина, но есть компромиссный

У нас нет никакого модификатора, который был бы internal внутри library group, но есть специальная аннотация @RequiresOptIn. Она дает возможность сообщить пользователю, что api is not meant to be public. Например, так это выглядит в корутинах:


@Retention(value = AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY)
@RequiresOptIn(
level = RequiresOptIn.Level.ERROR, message = "This is an internal kotlinx.coroutines API that " +
"should not be used from outside of kotlinx.coroutines. No compatibility guarantees are provided. " +
"It is recommended to report your use-case of internal API to kotlinx.coroutines issue tracker, " +
"so stable API could be provided instead"
)
public annotation class InternalCoroutinesApi



@InternalCoroutinesApi
public fun tryResume(value: T, idempotent: Any? = null): Any?


Теперь, чтобы вызвать tryResume, нам нужно явно добавить либо @OptIn(InternalCoroutinesApi::class) (если мы хотим "проглотить" ошибку), либо @InternalCoroutinesApi (если хотим пробросить ее дальше). В обоих случаях мы по сути подписываемся, что согласны на нестабильное api – то есть, технически все эти сущности публичные, но есть нюанс

При этом кейворд public может быть полезен, даже когда вам не нужно предоставлять внешнее api

Но об этом уже в следующем посте

🎃 Everlasting Loops
  • 👍 8
  • 🔥 5
  • ❤ 1
More from @loops_everlasting
  1. Jul 23, 2025невероятный успех #pull_request
  2. Jul 23, 2025Так выглядел вайбкодинг с Kiro (мем мой)
  3. Jul 23, 2025Post #25
  4. Jul 23, 2025Кстати, если вдруг хотите еще на кого-нибудь подписаться, есть целая папка с годными канал…
  5. Jul 23, 2025Пока готовил пост, заметил, что забыл в автокомплите точку с запятой
  6. Jul 23, 2025Еще к первому посту про плагин в комментарии прилетел фича-реквест от Асхара из канала Пол…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →