Требования к включению
Стандартная библиотека 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, вы можете добавить такие аргументы:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions.freeCompilerArgs += "-opt-in=org.mylibrary.OptInAnnotation"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
freeCompilerArgs += "-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 {}
Обратите внимание, что для некоторых языковых элементов аннотация требования к включению неприменима:
Вы не можете аннотировать вспомогательное поле или геттер свойства, только само свойство.
Вы не можете аннотировать локальную переменную или параметр значения.
Требования к включению для предварительно стабильных 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–2022 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