aSe*_*emy 3 operator-overloading assignment-operator kotlin gradle-kotlin-dsl
我有一个包含可变值的 Kotlin 类。
class StringWrapper(
var value: String = ""
) {
override fun toString(): String = value
}
Run Code Online (Sandbox Code Playgroud)
我使用这个包装器作为自定义数据持有者类中的属性
class DataHolder {
val name = StringWrapper()
override fun toString(): String = "Data(name=$name)"
}
Run Code Online (Sandbox Code Playgroud)
我想让它更容易地为内容赋值StringWrapper
val dataAlpha = DataHolder()
// the '.value' is unnecessary noise
dataAlpha.name.value = "alpha"
// I want to directly assign a string value, but I get an error
dataAlpha.name = "alpha" // ERROR Type mismatch.
// Required: StringWrapper
// Found: String
Run Code Online (Sandbox Code Playgroud)
我还想让复制一个StringWrapper到另一个变得更容易。
val dataAlpha = DataHolder()
dataAlpha.name = "alpha"
val dataAlphaCopy = DataHolder()
// I want to directly assign the value of `dataAlpha.name.value` into `dataAlphaCopy.name.value`
dataAlphaCopy.name = dataAlpha.name // ERROR Val cannot be reassigned
Run Code Online (Sandbox Code Playgroud)
据我所知,Gradle 8.1在 Kotlin DSL 中有一个新的实验性功能,可以满足我的需求。如何在我自己的库中引入相同的赋值运算符?
我尝试查看运算符重载文档,但没有引用赋值运算符。
有一个KEEP 语言提案引入了这样的功能,但它已被关闭。
我正在使用 Kotlin 1.8.20
有一个新的 Kotlin (v1.8.0) 编译器插件可用于提供运算符加载。
目前尚未公布,但已可供使用。它位于此处的 Kotlin 源代码中。它与 Gradle 在Gradle 版本 8.1 的Kotlin DSL 中使用的插件相同。
IntelliJ 中的支持可能有限 - 请确保您使用的是最新版本。
Kotlin 分配插件可以像其他 Kotlin 编译器插件一样应用。
在 Gradle 项目中,可以使用简单的 Gradle 插件来应用它。
我不熟悉使用 Maven、Ant 或通过 CLI 编译 Kotlin - 但请查看其他 Kotlin 编译器插件说明以获取类似说明。
Run Code Online (Sandbox Code Playgroud)$KOTLIN_HOME/bin/kotlinc-jvm -Xplugin=$KOTLIN_HOME/lib/assignment-compiler-plugin.jar -P plugin:org.jetbrains.kotlin.assignment:annotation=fqdn.SupportsKotlinAssignmentOverloading ...(您可以在 https://github.com/JetBrains/kotlin/blob/master/plugins/assign-plugin/assign-plugin.common/src/org/jetbrains/kotlin/assignment/plugin/AssignmentPluginNames 中查看所有字符串。千吨)
首先在你的项目中创建一个注释
package my.project
/** Denotes types that will be processed by the Kotlin Assignment plugin */
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class KotlinAssignmentOverloadTarget
Run Code Online (Sandbox Code Playgroud)
然后在 Gradle 中应用该插件,并将其配置为使用您的注释
plugins {
kotlin("plugin.assignment") version "1.8.10"
}
assignment {
annotation("my.project.KotlinAssignmentOverloadTarget")
}
Run Code Online (Sandbox Code Playgroud)
然后在您的代码中将注释应用到StringWrapper.
package my.project
/** Denotes types that will be processed by the Kotlin Assignment plugin */
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class KotlinAssignmentOverloadTarget
Run Code Online (Sandbox Code Playgroud)
我建议通常应将注释应用于包含一个(或可能多个)可变值的“包装器”类。它还可以应用于其他类似类实现的接口(这就是 Gradle 所做的)。
应用编译器插件并设置注释后,您就可以开始编写重载运算符。
plugins {
kotlin("plugin.assignment") version "1.8.10"
}
assignment {
annotation("my.project.KotlinAssignmentOverloadTarget")
}
Run Code Online (Sandbox Code Playgroud)
您现在可以直接将字符串分配给name属性
@KotlinAssignmentOverloadTarget
class StringWrapper(
var value: String = ""
) {
override fun toString(): String = value
}
Run Code Online (Sandbox Code Playgroud)
并且,使用扩展功能,将一个分配StringWrapper给另一个。
@KotlinAssignmentOverloadTarget
class StringWrapper(
var value: String = ""
) {
// member function
/** Provides overloaded setter for setting the value of [value] using an assignment syntax */
fun assign(value: String) {
this.value = value
}
}
// extension function
/** Provides overloaded setter for setting the value of [value] using an assignment syntax */
fun StringWrapper.assign(value: StringWrapper) {
this.value = value.value
}
Run Code Online (Sandbox Code Playgroud)
StringWrapper当类型的属性为s时,运算符重载将不起作用var。他们一定是vals。
val dataAlpha = DataHolder()
dataAlpha.name = "alpha"
println(dataAlpha) // prints: Data(name=alpha)
Run Code Online (Sandbox Code Playgroud)
请记住,赋值重载仅在属性是成员属性时才起作用。
因此,当存在StringWrapper不是类属性的值时,赋值重载器将不起作用。
val dataAlphaCopy = DataHolder()
dataAlphaCopy.name = dataAlpha.name
println(dataAlphaCopy) // prints: Data(name=alpha)
Run Code Online (Sandbox Code Playgroud)
手动调用该assign()函数,或创建一个具有属性的类。使用对象表达式也可以。
class MutableDataHolder {
var name = StringWrapper()
}
fun main() {
val dataAlpha = MutableDataHolder()
// no overload operator is generated, because name is a 'var'
dataAlpha.name = "alpha" // ERROR Type mismatch.
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
413 次 |
| 最近记录: |