Вы могли видеть такую функцию:
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