Kotlin:数字的一元加/减运算符是什么意思?

7
我在Kotlin中发现所有数字类型都已经定义了unaryPlusunaryMinus运算符。
这些运算符的目的是什么?它们与incdec的前缀形式有什么联系吗?
4个回答

13

其他人已经定义了unaryMinusunaryPlus的基本含义,在数字类型上它们甚至可能根本不被视为函数。例如,编码+xx.unaryPlus()会生成相同的字节码(其中x是类型Int):

ILOAD 1
ISTORE 2

而代码 -xx.unaryMinus() 会生成相同的字节码:

ILOAD 1
INEG
ISTORE 2

但实际情况比这更复杂...

所以编译器为什么会为+x生成任何内容呢?有些人会说+xx.unaryPlus()什么也没做,-xx.unaryMinus()只是改变符号。这是不正确的。在Java中更加复杂,因为它可能涉及到扩展和拆箱,详见一元数值提升,其中解释了这些运算符的全部后果。这对于装箱值和小于Int类型的类型都有影响。对于类型为ShortByte的值,这些运算符将返回一个新的拆箱值,其类型为Int。而由于两个运算符都具有这种更隐含的功能,因此即使您认为+x没有作用,它们都必须生成字节码。顺便说一下,这类似于C语言的做法,称为Usual Arithmetic Conversions

因此,此代码无效:

val x: Short = 1
val y1: Short = +x              // incompatible types
val y2: Short = x.unaryPlus()   // incompatible types
val z1: Short = -x              // incompatible types
val z2: Short = x.unaryMinus()  // incompatible types

在基本数值类型的这些数值情况下,它们只是编译器魔法,允许将这些运算符的概念等同于您可能想要在其他类中重载的运算符函数。

对于其他用途,如运算符重载......

但它们不仅适用于数学用途,还可以用于任何类作为运算符。 Kotlin将运算符公开为函数,以便您可以在特定一组运算符上应用运算符重载,其中包括unaryMinusunaryPlus

我可以使用这些来为自己或现有类定义运算符。例如,我有一个Set<Things>,其中Things是一个枚举类,同时具有unaryMinus()运算符来否定有限选项集的内容:

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

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

然后,我可以随时否定我的枚举集合:

val current = setOf(Things.THREE, Things.FIVE)
println(-current)       // [ONE, TWO, FOUR]
println(-(-current))    // [THREE, FIVE]

需要注意的是,我必须使用修饰符operator来声明我的扩展函数,否则它将无法工作。如果您忘记在使用运算符时添加此修饰符,编译器将提醒您:

Error:(y, x) Kotlin: 'operator' modifier is required on 'unaryMinus' in 'com.my.favorite.package.SomeClass'


真正完整的答案。谢谢! - Jire

9
这些运算符是整数的符号。以下是一些示例: +5 调用 5.unaryPlus() 并返回 5。 -5 调用 5.unaryMinus() 并返回 -5。 -(-5) 调用 5.unaryMinus().unaryMinus() 并返回 5。

非常有道理! - Jire

3

这些运算符的目的是为了能够编写以下代码:

val a = System.nanoTime()
val b = -a // a.unaryMinus()
val c = +b // b.unaryPlus()

它们与++/inc--/dec运算符没有直接关系,但可以结合使用。

请注意以下表达式是不同的:

--a // a = a.dec()
-(-a) // a.unaryMinus().unaryMinus()

1
fun main(){
var a = 34
var b = 56


println("Orignal value:"+ a)
println("Orignal value:"+ b

//The value will not change using .unaryPlus() will generate bytecode
println("After unary plus:" + a.unaryPlus())
//The value will invert the sign using .unaryMinus() will generate bytecode
println("After unary minus:" + b.unaryMinus())

}

Solution:
Orignal value:34
Orignal value:56
After unary plus:35
After unary minus:-55

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接