kotlin更多语言结构——>选择加入要求

  1.3.70 中引入了 @RequireOptIn 与 @OptIn 注解以取代先前使用的 @Experimental 与 @UseExperimental;同时 -Xopt-in 编译器选项也取代了 -Xuse-experimental。

  Kotlin 标准库提供了一种机制,用于要求并明确同意使用 API 的某些元素。通过这种机制,库开发人员可以将使 用其 API 需要选择加入的特定条件告知用戶,例如,如果某个 API 处于实验状态,并且将来可能会更改。

  为了避免潜在的问题,编译器会向此类 API 的用戶发出警告,告知他们这些条件,并要求他们在使用 API 之前选 择加入

 

选择使用API

  如果库作者将一个库的 API 声明标记为要求选择加入 你应该明确同意在代码中使用它。有多种方式可以选择加入使用此类 API,所有方法均不受技术限制。你可以*选择最适合自己的方式。

 

传播选择加入

  在使用供第三方(库)使用的 API 时,你也可以把其选择加入的要求传播到自己的 API。为此,请在你的 API 主体 声明中添加注解 要求选择加入的注解。这可以让你使用带有此注解的 API 元素。

// 库代码
@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 // 要求选择加入的注解
@MyDateTime
class DateProvider // 要求选择加入的类

  

// 客戶端代码
fun getYear(): Int {
    val dateProvider: DateProvider // 错误:DateProvider 要求选择加入
    // ...
}
@MyDateTime
fun getDate(): Date {
    val dateProvider: DateProvider // OK:该函数也需要选择加入 
    // ...
}
fun displayDate() {
    println(getDate()) // 错误:getDate() 需要选择加入
}

  如本例所示,带注释的函数看起来是 @MyDateTime API 的一部分。因此,这种选择加入会将选择加入的要求 传播到客戶端代码;其客戶将看到相同的警告消息,并且也必须同意。要使用多个需要选择加入的API,请在声明中标记所有需要选择加入的注解

 

非传播的用法

  在不公开其自身API的模块(例如应用程序)中,你可以选择使用 API 而无需将选择加入的要求传播到代码中。这种情况下,请使用 @OptIn 标记你的声明,并以要求选择加入的注解作为参数

// 库代码
@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 // 要求选择加入的注解

@MyDateTime
class DateProvider // 要求选择加入的类

  

//客戶端代码
@OptIn(MyDateTime::class)
fun getDate(): Date { // 使用 DateProvider;不传播选择加入的要求
val dateProvider: DateProvider
    // ...
}

fun displayDate() {
    println(getDate()) // OK:不要求选择加入
}

  当有人调用函数 getDate() 时,不会通知他们函数主体中使用的选择加入 API 的要求。

  要在一个文件的所有函数和类中使用要求选择加入的 API,请在文件的顶部,文件包说明和导入声明前添加文件级注释 @file:OptIn

 //客戶端代码 
@file:OptIn(MyDateTime::class)

  

模块范围的选择加入

  如果你不想在使用要求选择加入 API 的每个地方都添加注解,则可以为整个模块选择加入这些 API。要选择在 模块中使用 API,请使用参数 -Xopt-in 进行编译,使用 -Xopt-in = org.mylibrary.OptInAnnotation 指定该 API 使用的要求选择加入注解的标准名称。使用此参数进行编 译的效果与模块中每个声明都有注解 @OptIn(OptInAnnotation::class) 的效果相同。

  如果使用 Gradle 构建模块,可以添加如下参数

tasks.withType(KotlinCompile).configureEach {
     kotlinOptions {
        freeCompilerArgs += "-Xopt-in=org.mylibrary.OptInAnnotation" 
    }
}

  

tasks.withType<KotlinCompile>().configureEach {
    kotlinOptions.freeCompilerArgs += "-Xopt-in=org.mylibrary.OptInAnnotation"
}

  如果你的 Gradle 模块是多平台模块,请使用 useExperimentalAnnotation 方法

sourceSets {
    all {
        languageSettings { 
            useExperimentalAnnotation('org.mylibrary.OptInAnnotation')
        } 
    }
}

  

sourceSets {
    all {
        languageSettings.useExperimentalAnnotation("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>-Xopt-in =org.mylibrary.OptInAnnotation</arg>
                </args>
            </configuration>
        </plugin>
    </plugins>
</build>

  要在模块级别选择加入多个 API,请为每个要求选择加入的 API 添加以上描述的参数之一

 

要求选择加入 API

要求选择加入的注解

  如果想获得使用者使用你的模块 API 的明确同意,请创建一个注解类,作为_要求选择加入的注解_。这个类必须 使用 @RequiresOptIn 注解:

@RequiresOptIn
@Retention(AnnotationRetention.BINARY) 
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) 
annotation class MyDateTime

  

  要求选择加入的注解必须满足以下几个要求:

    — BINARY retention
    — targets中没有 EXPRESSION 与 FILE

    — 没有参数

  选择加入的要求可以具有以下两个严格级别之一:

    — RequiresOptIn.Level.ERROR 。选择加入是强制性的。否则,使用标记 API 的代码将无法编译。默认级别。

    — RequiresOptIn.Level.WARNING 。选择加入不是强制性的,而是建议使用的。没有它,编译器会发出警告。

  要设置所需的级别,请指定 @RequiresOptIn 注解的 level 参数

 

  另外,你可以提供一个 message 来通知用戶有关使用该 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 并在弃 用 message 中提供说明

@Deprecated("This opt-in requirement is not used anymore. Remove its usages from your code.") 
@RequiresOptIn
annotation class ExperimentalDateTime

  

 

选择加入要求的实验状态

  选择加入要求的机制在 Kotlin 1.3 中是实验性的。这意味着在将来的版本中,可能会以不兼容的方式进行更改。

   为了让使用注解 @OptIn 和 @RequiresOptIn 的用戶了解其实验状态,编译器会在编译代码时发出警告:

  This class can only be used with the compiler argument '-Xopt- in=kotlin.RequiresOptIn'

  要移除警告,请添加编译器参数 -Xopt-in=kotlin.RequiresOptIn 。

 

 

 

 

 

上一篇:环境变量


下一篇:实现一个做双向NAT的虚拟网卡