Требования к включению
Стандартная библиотека Kotlin предоставляет механизм для требования и предоставления явного согласия на использование определенных элементов API. Этот механизм позволяет разработчикам библиотек информировать пользователей о своих API о конкретных условиях, требующих включения, например, если API находится в экспериментальном состоянии и, вероятно, изменится в будущем.
Чтобы предотвратить возможные проблемы, компилятор предупреждает пользователей о таких API об этих условиях и требует их включения перед использованием API.
Включение использования API
Если автор библиотеки помечает объявление из API библиотеки как требующее включения, вы должны дать явное согласие на его использование в вашем коде. Существует несколько способов включения таких API, все они применимы без технических ограничений. Вы вольны выбрать способ, который вам больше подходит.
Распространение включения
Когда вы используете API в коде, предназначенном для использования третьими лицами (библиотека), вы можете распространить его требование к включению на ваш API. Для этого добавьте в свое объявление аннотацию требования к включению используемого API в его теле. Это позволит вам использовать элементы API, требующие включения.
// Library code @RequiresOptIn(message = "This API is experimental. It may be changed in the future without notice.") @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class MyDateTime // Opt-in requirement annotation @MyDateTime class DateProvider // A class requiring opt-in
// Client code
fun getYear(): Int {
val dateProvider: DateProvider // Error: DateProvider requires opt-in
// ...
}
@MyDateTime
fun getDate(): Date {
val dateProvider: DateProvider // OK: the function requires opt-in as well
// ...
}
fun displayDate() {
println(getDate()) // Error: getDate() requires opt-in
}
Как видно из этого примера, аннотированная функция, кажется, является частью @MyDateTime API. Таким образом, такое включение распространяет требование к включению на код клиента; его клиенты увидят то же сообщение об ошибке и также будут обязаны согласиться.
Неявные использования API, требующих включения, также требуют включения. Если элемент API не имеет аннотации требования к включению, но его сигнатура включает тип, объявленный как требующий включения, его использование все равно вызовет предупреждение. См. пример ниже.
// Client code
fun getDate(dateProvider: DateProvider): Date { // Error: DateProvider requires opt-in
// ...
}
fun displayDate() {
println(getDate()) // Warning: the signature of getDate() contains DateProvider, which requires opt-in
}
Для использования нескольких API, требующих включения, пометьте объявление всеми их аннотациями требования к включению.
Нераспространяемое включение
В модулях, которые не экспонируют собственный API, такие как приложения, вы можете включить использование API без распространения требования к включению на ваш код. В этом случае пометьте объявление @OptIn, передавая аннотацию требования к включению в качестве аргумента:
// Library code @RequiresOptIn(message = "This API is experimental. It may be changed in the future without notice.") @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class MyDateTime // Opt-in requirement annotation @MyDateTime class DateProvider // A class requiring opt-in
// Client code
@OptIn(MyDateTime::class)
fun getDate(): Date { // Uses DateProvider; doesn't propagate the opt-in requirement
val dateProvider: DateProvider
// ...
}
fun displayDate() {
println(getDate()) // OK: opt-in is not required
}
Когда кто-то вызовет функцию getDate(), они не будут проинформированы о требованиях к включению для API, используемых в ее теле.
Обратите внимание, что если @OptIn применяется к объявлению, сигнатура которого содержит тип, объявленный как требующий включения, включение все равно будет распространено:
// Client code
@OptIn(MyDateTime::class)
fun getDate(dateProvider: DateProvider): Date { // Has DateProvider as a part of a signature; propagates the opt-in requirement
// ...
}
fun displayDate() {
println(getDate()) // Warning: getDate() requires opt-in
}
Чтобы использовать API, требующее включения, во всех функциях и классах в файле, добавьте аннотацию на уровне файла @file:OptIn в начало файла, перед указанием пакета и импортами.
// Client code @file:OptIn(MyDateTime::class)
Модульное включение
Если вы не хотите аннотировать каждое использование API, требующего включения, вы можете включить их для всего модуля. Для включения использования API в модуле скомпилируйте его с аргументом -opt-in, указав полное квалифицированное имя аннотации требования к включению используемого API: -opt-in=org.mylibrary.OptInAnnotation. Компиляция с этим аргументом эквивалентна добавлению аннотации @OptIn(OptInAnnotation::class) к каждому объявлению в модуле.
Если вы строит свой модуль с помощью Gradle, вы можете добавить аргументы так:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
// ...
tasks.named<KotlinCompilationTask<*>>("compileKotlin").configure {
compilerOptions.freeCompilerArgs.add("-opt-in=org.mylibrary.OptInAnnotation")
}
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
// ...
tasks.named('compileKotlin', KotlinCompilationTask) {
compilerOptions {
freeCompilerArgs.add("-opt-in=org.mylibrary.OptInAnnotation")
}
}
Если ваш модуль Gradle является многоплатформенным модулем, используйте метод optIn:
sourceSets {
all {
languageSettings.optIn("org.mylibrary.OptInAnnotation")
}
}
sourceSets {
all {
languageSettings {
optIn('org.mylibrary.OptInAnnotation')
}
}
}
Для Maven это будет:
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>...</executions>
<configuration>
<args>
<arg>-opt-in=org.mylibrary.OptInAnnotation</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
Для включения нескольких API на уровне модуля добавьте один из описанных аргументов для каждого маркера требования к включению, используемого в вашем модуле.
Требовать включение для API
Создать аннотации требования к включению
Если вы хотите потребовать явного согласия на использование API вашего модуля, создайте класс аннотаций, который будет использоваться в качестве аннотации требования к включению. Этот класс должен быть аннотирован с помощью @RequiresOptIn:
@RequiresOptIn @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class MyDateTime
Аннотации требования к включению должны удовлетворять нескольким требованиям:
BINARYилиRUNTIMEсохранениеБез
EXPRESSION,FILE,TYPE, илиTYPE_PARAMETERсреди целейБез параметров.
Требование включения может иметь один из двух уровней серьезности уровней:
RequiresOptIn.Level.ERROR. Включение обязательно. В противном случае код, использующий помеченный API, не будет компилироваться. Уровень по умолчанию.RequiresOptIn.Level.WARNING. Включение не обязательно, но желательно. Без него компилятор выдает предупреждение.
Для установки нужного уровня укажите параметр level аннотации @RequiresOptIn.
Кроме того, вы можете предоставить message для информирования пользователей API об особых условиях использования API. Компилятор покажет его пользователям, которые используют API без включения.
@RequiresOptIn(level = RequiresOptIn.Level.WARNING, message = "This API is experimental. It can be incompatibly changed in the future.") @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class ExperimentalDateTime
Если вы публикуете несколько независимых функций, требующих включения, объявляйте аннотацию для каждой. Это делает использование API безопаснее для ваших клиентов: они могут использовать только те функции, которые они явно принимают. Это также позволяет вам независимо отключать требования к включению для функций.
Помечать элементы API
Для того, чтобы потребовать включение для использования элемента API, аннотируйте его объявление аннотацией требования к включению:
@MyDateTime
class DateProvider
@MyDateTime
fun getTime(): Time {}
Обратите внимание, что для некоторых языковых элементов аннотация требования к включению неприменима:
Вы не можете аннотировать вспомогательное поле или getter свойства, только само свойство.
Вы не можете аннотировать локальную переменную или параметр значения.
Требования к включению для предварительно стабильных API
Если вы используете требования к включению для функций, которые еще не стабильны, тщательно обрабатывайте переход API к стабильному состоянию, чтобы не сломать код клиента.
После того, как ваш предварительно стабильный API перейдет в стабильное состояние, удалите его аннотации требования к включению из объявлений. Клиенты смогут использовать их без ограничений. Однако вы должны оставить классы аннотаций в модулях, чтобы существующий код клиента оставался совместимым.
Чтобы позволить пользователям API обновить свои модули соответственно (удалить аннотации из своего кода и перекомпилировать), пометьте аннотации как @Deprecated и предоставьте объяснение в сообщении о устаревании.
@Deprecated("This opt-in requirement is not used anymore. Remove its usages from your code.")
@RequiresOptIn
annotation class ExperimentalDateTime
© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/opt-in-requirements.html