The Kotlin standard library provides a mechanism for requiring and explicitly agreeing to use certain elements of the API. Through this mechanism, library developers can inform users of the specific conditions that need to be selected and added to use their API. For example, if an API is in experimental state and may be changed in the future.
To avoid potential problems, the compiler warns users of such APIs about these conditions and asks them to opt in before using the API
Choose to use API
If the library author marks a library's API declaration as optional, you should explicitly agree to use it in your code. There are many ways to choose to join and use such APIs, and all methods are not subject to technical restrictions. You are free to choose the best way for yourself.
Spread choice to join
When using an API for a third party (Library), you can also spread the requirements it chooses to join to your own API. To do this, please add comments in your API body declaration. You are required to select the comments to be added. This allows you to use API elements with this annotation.
// 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 // Note required to be added @MyDateTime class DateProvider // It is required to select the added class
// Client code fun getYear(): Int { val dateProvider: DateProvider // Error: DateProvider requires you to select join // ... } @MyDateTime fun getDate(): Date { val dateProvider: DateProvider // OK: this function also needs to be added // ... } fun displayDate() { println(getDate()) // Error: getDate() needs to select join }
As this example shows, the annotated function appears to be part of the @ MyDateTime API. Therefore, this optional join will propagate the request of optional join to the client code; Their customers will see the same warning message and must also agree. To use multiple APIs that need to be selected, mark all annotations that need to be selected in the declaration
Non communicable usage
In a module that does not expose its own API (such as an application), you can choose to use the API without propagating the requirements you choose to add to the code. In this case, please mark your declaration with @ OptIn and take the annotation required as the parameter
// 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 // Note required to be added @MyDateTime class DateProvider // It is required to select the added class
//Client code @OptIn(MyDateTime::class) fun getDate(): Date { // Use DateProvider; Do not propagate opt in requirements val dateProvider: DateProvider // ... } fun displayDate() { println(getDate()) // OK: you are not required to choose to join }
When someone calls the function getDate(), they will not be notified of the requirement to choose to join the API used in the function body.
To use the API that requires optional addition in all functions and classes of a file, please add a file level comment @ file:OptIn at the top of the file and before the package description and import declaration
//Client code @file:OptIn(MyDateTime::class)
Selection and addition of module scope
If you don't want to add annotations everywhere you use the API, you can choose to add these APIs for the whole module. To choose to use the API in the module, compile with the parameter - xopt in, using - xopt in = org mylibrary. Optinannotation specifies the standard name used by the API to select and annotate. The effect of compiling with this parameter is the same as that of @ OptIn(OptInAnnotation::class) annotation for each declaration in the module.
If you use Gradle to build a module, you can add the following parameters
tasks.withType(KotlinCompile).configureEach { kotlinOptions { freeCompilerArgs += "-Xopt-in=org.mylibrary.OptInAnnotation" } }
tasks.withType<KotlinCompile>().configureEach { kotlinOptions.freeCompilerArgs += "-Xopt-in=org.mylibrary.OptInAnnotation" }
If your Gradle module is a multi platform module, please use useExperimentalAnnotation method
sourceSets { all { languageSettings { useExperimentalAnnotation('org.mylibrary.OptInAnnotation') } } }
sourceSets { all { languageSettings.useExperimentalAnnotation("org.mylibrary.OptInAnnotation") } }
For Maven, it would be:
<build> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${ kotlin.version }</version> <executions>...</executions> <configuration> <args> <arg>-Xopt-in =org.mylibrary.OptInAnnotation</arg> </args> </configuration> </plugin> </plugins> </build>
To select multiple APIs at the module level, add one of the parameters described above for each API that requires selection
It is required to select and join API
Note required to be added
If you want the user's explicit consent to use your module API, please create an annotation class as_ It is required to select the added annotation. This class must be annotated with @ RequiresOptIn:
@RequiresOptIn @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class MyDateTime
It is required that the selected annotation must meet the following requirements:
— BINARY retention
- no EXPRESSION and FILE in targets
- no parameters
The requirements selected for inclusion can have one of the following two levels of strictness:
— RequiresOptIn.Level.ERROR . Opt in is mandatory. Otherwise, code that uses the markup API cannot be compiled. Default level.
— RequiresOptIn.Level.WARNING . Opt in is not mandatory, but recommended. Without it, the compiler will issue a warning.
To set the required level, specify the level parameter of the @ RequiresOptIn annotation
In addition, you can provide a message to inform users about specific conditions for using the API. The compiler displays it to users who use the API but do not choose to join
@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
If you publish multiple independent functions that need to be added, please declare a comment for each function. This makes it safer for your users to use the API: they can only use the functions they explicitly accept. This also allows you to independently delete the requirement of optional addition from the function
Tag API elements
To require opt in when using an API, add a comment to its declaration that requires opt in
@MyDateTime class DateProvider @MyDateTime fun getTime(): Time {}
Selection and addition requirements of API before stabilization
If you are required to add features that are not yet stable, please carefully handle the API transition from experimental state to stable state to avoid damaging the client code.
When the pre stable API is stable and released in a stable state, please delete the annotations it requires to be added from the declaration. Clients will be able to use them without restrictions. However, you should leave the annotation class in the module to be compatible with the existing client code.
In order for API users to update their modules accordingly (remove annotations from the code and recompile), mark the annotations @ Deprecated and provide a description in the Deprecated message
@Deprecated("This opt-in requirement is not used anymore. Remove its usages from your code.") @RequiresOptIn annotation class ExperimentalDateTime
Select the required experimental state
The mechanism for choosing to join the requirements is experimental in Kotlin 1.3. This means that changes may be made in an incompatible manner in future releases.
In order to let users who use the annotation @ OptIn and @ RequiresOptIn know their experimental status, the compiler will issue a warning when compiling the code:
This class can only be used with the compiler argument '-Xopt- in=kotlin.RequiresOptIn'
To remove the warning, add the compiler parameter - xopt in = kotlin RequiresOptIn .