gpt4 book ai didi

operator-overloading - 在 Kotlin 中,我可以覆盖一些现有的运算符,但是创建新的运算符呢?

转载 作者:IT老高 更新时间:2023-10-28 13:45:12 26 4
gpt4 key购买 nike

在 Kotlin 中,我看到我可以通过函数 plus() 覆盖 + 以及通过函数 覆盖 * 一些运算符>times() ...但对于某些东西,比如集合,不存在首选的(集合论)符号/运算符。例如 A∩B 表示交集,A∪B 表示并集。

我似乎无法定义自己的运算符,没有明确的语法来说明运算符使用什么符号。例如,如果我想为 $$ 创建一个函数作为运算符:

operator fun String.$$(other: String) = "$this !!whatever!! $other"
// or even
operator fun String.whatever(other: String) = "$this !!whatever!! $other" // how do I say this is the $$ symbol?!?

我得到了同样的错误:

Error:(y, x) Kotlin: 'operator' modifier is inapplicable on this function: illegal function name

可以创建或覆盖哪些运算符的规则是什么?

注意: 作者有意编写并回答了这个问题 (Self-Answered Questions ),因此常见的 Kotlin 主题的惯用答案出现在 SO 中。

最佳答案

Kotlin 只允许一组非常特殊的 operators to be overridden并且您不能更改可用运算符的列表。

在覆盖运算符时应小心,以保持原始运算符的精神或数学符号的其他常见用法。但有时典型的符号不可用。例如设置联合 可以很容易地视为 +因为从概念上讲它是有意义的,这是一个内置运算符 Set<T>.plus() Kotlin 已经提供了,或者您可以发挥创意并使用 infix function对于这种情况:

// already provided by Kotlin:
// operator fun <T> Set<T>.plus(elements: Iterable<T>): Set<T>

// and now add my new one, lower case 'u' is pretty similar to math symbol ∪
infix fun <T> Set<T>.u(elements: Set<T>): Set<T> = this.plus(elements)

// and therefore use any of...
val union1 = setOf(1,2,5) u setOf(3,6)
val union2 = setOf(1,2,5) + setOf(3,6)
val union3 = setOf(1,2,5) plus setOf(3,6)

或者更清楚的是:

infix fun <T> Set<T>.union(elements: Set<T>): Set<T> = this.plus(elements)

// and therefore
val union4 = setOf(1,2,5) union setOf(3,6)

继续您的集合运算符列表,交集是符号 所以假设每个程序员都有一个字母'n'看起来的字体我们可以侥幸逃脱:

infix fun <T> Set<T>.n(elements: Set<T>): Set<T> = this.intersect(elements)

// and therefore...
val intersect = setOf(1,3,5) n setOf(3,5)

或通过 * 的运算符重载如:

operator fun <T> Set<T>.times(elements: Set<T>): Set<T> = this.intersect(elements)  

// and therefore...
val intersect = setOf(1,3,5) * setOf(3,5)

虽然您已经可以使用现有的标准库中缀函数 intersect() 如:

val intersect = setOf(1,3,5) intersect setOf(3,5)

如果您要发明新事物,则需要选择最接近的运算符或函数名称。例如否定一组枚举,可能使用 -运算符 ( unaryMinus() ) 或 !运算符(not()):

enum class Things {
ONE, TWO, THREE, FOUR, FIVE
}

operator fun Set<Things>.unaryMinus() = Things.values().toSet().minus(this)
operator fun Set<Things>.not() = Things.values().toSet().minus(this)

// and therefore use any of...

val current = setOf(Things.THREE, Things.FIVE)

println(-current) // [ONE, TWO, FOUR]
println(-(-current)) // [THREE, FIVE]
println(!current) // [ONE, TWO, FOUR]
println(!!current) // [THREE, FIVE]
println(current.not()) // [ONE, TWO, FOUR]
println(current.not().not()) // [THREE, FIVE]

请慎重考虑,因为运算符重载可能非常有用,否则会导致困惑和困惑。您必须在保持代码可读性的同时决定什么是最好的。有时,如果运算符符合该符号的规范,或者与原始符号相似的中缀替换,或者使用描述性词以避免混淆,则该运算符是最佳的。

始终检查 Kotlin Stdlib API Reference因为可能已经定义了许多您想要的运算符,或者具有等效的扩展函数。

另一件事......

关于你的$$运算符,从技术上讲,您可以这样做:

infix fun String.`$$`(other: String) = "$this !!whatever!! $other"

但是因为需要对函数名进行转义,调用起来会很丑:

val text = "you should do" `$$` "you want"

这并不是真正的运算符重载,只有当它是 can me made infix 的函数时才有效。 .

关于operator-overloading - 在 Kotlin 中,我可以覆盖一些现有的运算符,但是创建新的运算符呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39410946/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com