【问题标题】:Kotlin: What do the unary plus/minus operators do on numbers?Kotlin:一元加/减运算符对数字有什么作用?
【发布时间】:2016-09-09 07:40:04
【问题描述】:

我注意到在 Kotlin 中已经在所有数字类型上定义了 unaryPlusunaryMinus 运算符。

这些运算符的目的是什么?它们是否以某种方式连接到incdec 的前缀形式?

【问题讨论】:

    标签: operators kotlin


    【解决方案1】:

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

    ILOAD 1
    ISTORE 2
    

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

    ILOAD 1
    INEG
    ISTORE 2
    

    但还有更多事情要做……

    那么为什么编译器甚至会为+x 生成任何东西?有人会说+xx.unaryPlus() 什么都不做,而-xx.unaryMinus() 只是反转符号。那是不正确的。在 Java 中它更复杂,因为它可能涉及扩展和拆箱,请参阅Unary Numeric Promotion,它解释了这些运算符的全部后果。这会对小于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 将运算符公开为函数,以便您可以将 operator overloading 应用于一组特定的运算符,包括 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 声明我的扩展函数,否则这将不起作用。如果您在尝试使用运算符时忘记了这一点,编译器会提醒您:

    错误:(y, x) Kotlin: 'com.my.favorite.package.SomeClass' 中的 'unaryMinus' 需要 'operator' 修饰符

    【讨论】:

    • 真正完整的答案。谢谢!
    【解决方案2】:

    这些运算符是整数的符号。以下是一些示例:

    +5 调用 5.unaryPlus() 并返回 5。

    -5 调用 5.unaryMinus() 并返回 -5。

    -(-5) 调用 5.unaryMinus().unaryMinus() 并返回 5。

    【讨论】:

    • 很有道理!
    【解决方案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()
    

    【讨论】:

      【解决方案4】:
      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
      

      【讨论】:

        猜你喜欢
        • 2010-10-18
        • 2021-06-06
        • 2011-07-23
        • 2013-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-01
        相关资源
        最近更新 更多