美文网首页Android开发经验谈程序员Android开发
Kotlin操作符重载与中缀表示法笔记

Kotlin操作符重载与中缀表示法笔记

作者: dengyin2000 | 来源:发表于2018-02-16 01:18 被阅读472次

    1.操作符重载

    操作符重载在java中并没有这样的概念,它可以让我们为指定的类型提供预定义的一组操作符实现。这些操作符具有固定的符号表示(如+、* 或 in)和固定的优先级。怎样实现操作符重载呢?其实只要你实现一个固定名称的函数,然后用operator来修饰这个函数。查看Kotlin源码可以发现有大量的操作符重载的实现,我们来看看Int类型做了那些操作符重载。

        /**
         * Compares this value with the specified value for order.
         * Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
         * or a positive number if it's greater than other.
         */
        public operator fun compareTo(other: Byte): Int
    
        /**
         * Compares this value with the specified value for order.
         * Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
         * or a positive number if it's greater than other.
         */
        public operator fun compareTo(other: Short): Int
    
        /**
         * Compares this value with the specified value for order.
         * Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
         * or a positive number if it's greater than other.
         */
        public override operator fun compareTo(other: Int): Int
    
        /**
         * Compares this value with the specified value for order.
         * Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
         * or a positive number if it's greater than other.
         */
        public operator fun compareTo(other: Long): Int
    
        /**
         * Compares this value with the specified value for order.
         * Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
         * or a positive number if it's greater than other.
         */
        public operator fun compareTo(other: Float): Int
    
        /**
         * Compares this value with the specified value for order.
         * Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
         * or a positive number if it's greater than other.
         */
        public operator fun compareTo(other: Double): Int
    
        /** Adds the other value to this value. */
        public operator fun plus(other: Byte): Int
        /** Adds the other value to this value. */
        public operator fun plus(other: Short): Int
        /** Adds the other value to this value. */
        public operator fun plus(other: Int): Int
        /** Adds the other value to this value. */
        public operator fun plus(other: Long): Long
        /** Adds the other value to this value. */
        public operator fun plus(other: Float): Float
        /** Adds the other value to this value. */
        public operator fun plus(other: Double): Double
    
        /** Subtracts the other value from this value. */
        public operator fun minus(other: Byte): Int
        /** Subtracts the other value from this value. */
        public operator fun minus(other: Short): Int
        /** Subtracts the other value from this value. */
        public operator fun minus(other: Int): Int
        /** Subtracts the other value from this value. */
        public operator fun minus(other: Long): Long
        /** Subtracts the other value from this value. */
        public operator fun minus(other: Float): Float
        /** Subtracts the other value from this value. */
        public operator fun minus(other: Double): Double
    
        /** Multiplies this value by the other value. */
        public operator fun times(other: Byte): Int
        /** Multiplies this value by the other value. */
        public operator fun times(other: Short): Int
        /** Multiplies this value by the other value. */
        public operator fun times(other: Int): Int
        /** Multiplies this value by the other value. */
        public operator fun times(other: Long): Long
        /** Multiplies this value by the other value. */
        public operator fun times(other: Float): Float
        /** Multiplies this value by the other value. */
        public operator fun times(other: Double): Double
    
        /** Divides this value by the other value. */
        public operator fun div(other: Byte): Int
        /** Divides this value by the other value. */
        public operator fun div(other: Short): Int
        /** Divides this value by the other value. */
        public operator fun div(other: Int): Int
        /** Divides this value by the other value. */
        public operator fun div(other: Long): Long
        /** Divides this value by the other value. */
        public operator fun div(other: Float): Float
        /** Divides this value by the other value. */
        public operator fun div(other: Double): Double
    
        /** Calculates the remainder of dividing this value by the other value. */
        @Deprecated("Use rem(other) instead", ReplaceWith("rem(other)"), DeprecationLevel.WARNING)
        public operator fun mod(other: Byte): Int
        /** Calculates the remainder of dividing this value by the other value. */
        @Deprecated("Use rem(other) instead", ReplaceWith("rem(other)"), DeprecationLevel.WARNING)
        public operator fun mod(other: Short): Int
        /** Calculates the remainder of dividing this value by the other value. */
        @Deprecated("Use rem(other) instead", ReplaceWith("rem(other)"), DeprecationLevel.WARNING)
        public operator fun mod(other: Int): Int
        /** Calculates the remainder of dividing this value by the other value. */
        @Deprecated("Use rem(other) instead", ReplaceWith("rem(other)"), DeprecationLevel.WARNING)
        public operator fun mod(other: Long): Long
        /** Calculates the remainder of dividing this value by the other value. */
        @Deprecated("Use rem(other) instead", ReplaceWith("rem(other)"), DeprecationLevel.WARNING)
        public operator fun mod(other: Float): Float
        /** Calculates the remainder of dividing this value by the other value. */
        @Deprecated("Use rem(other) instead", ReplaceWith("rem(other)"), DeprecationLevel.WARNING)
        public operator fun mod(other: Double): Double
    
        /** Calculates the remainder of dividing this value by the other value. */
        @SinceKotlin("1.1")
        public operator fun rem(other: Byte): Int
        /** Calculates the remainder of dividing this value by the other value. */
        @SinceKotlin("1.1")
        public operator fun rem(other: Short): Int
        /** Calculates the remainder of dividing this value by the other value. */
        @SinceKotlin("1.1")
        public operator fun rem(other: Int): Int
        /** Calculates the remainder of dividing this value by the other value. */
        @SinceKotlin("1.1")
        public operator fun rem(other: Long): Long
        /** Calculates the remainder of dividing this value by the other value. */
        @SinceKotlin("1.1")
        public operator fun rem(other: Float): Float
        /** Calculates the remainder of dividing this value by the other value. */
        @SinceKotlin("1.1")
        public operator fun rem(other: Double): Double
    
        /** Increments this value. */
        public operator fun inc(): Int
        /** Decrements this value. */
        public operator fun dec(): Int
        /** Returns this value. */
        public operator fun unaryPlus(): Int
        /** Returns the negative of this value. */
        public operator fun unaryMinus(): Int
    
         /** Creates a range from this value to the specified [other] value. */
        public operator fun rangeTo(other: Byte): IntRange
         /** Creates a range from this value to the specified [other] value. */
        public operator fun rangeTo(other: Short): IntRange
         /** Creates a range from this value to the specified [other] value. */
        public operator fun rangeTo(other: Int): IntRange
         /** Creates a range from this value to the specified [other] value. */
        public operator fun rangeTo(other: Long): LongRange
    
        /** Shifts this value left by the [bitCount] number of bits. */
        public infix fun shl(bitCount: Int): Int
        /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with copies of the sign bit. */
        public infix fun shr(bitCount: Int): Int
        /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with zeros. */
        public infix fun ushr(bitCount: Int): Int
        /** Performs a bitwise AND operation between the two values. */
        public infix fun and(other: Int): Int
        /** Performs a bitwise OR operation between the two values. */
        public infix fun or(other: Int): Int
        /** Performs a bitwise XOR operation between the two values. */
        public infix fun xor(other: Int): Int
    

    2. 一元操作

    2.1 一元前缀操作符

    表达式 翻译为
    +a a.unaryPlus()
    -a a.unaryMinus()
    !a a.not()

    当编译器处理+a时,它执行以下步骤:

    • 确定a实例的类型,如果类似为T。
    • 在T类型中查找一个带有operator修饰符的无参函数unaryPlus(),可以是成员函数或者扩展函数。
    • 如果没有找到,则会发生编译错误。

    下面代码展示下如何实现一个一元减运算符的示例:

    data class Point(val x: Int, val y: Int)
    
    operator fun Point.unaryMinus() : Point = Point(-x, -y)
    
    fun main(args: Array<String>) {
        val p = Point(1, 2)
        println(p)  //打印Point(x=1, y=2)
        println(-p)  //打印Point(x=-1, y=-2)
    }
    

    2.2 递增与递减

    表达式 翻译为
    a++ a.inc()
    a-- a.dec()

    下面示例下用法:

    data class Point(val x: Int, val y: Int)
    
    operator fun Point.unaryMinus() : Point = Point(-x, -y)
    
    operator fun Point.inc(): Point = Point(x + 1, y + 1)
    
    operator fun Point.dec(): Point = Point(x - 1, y - 1)
    

    3. 二元操作符

    3.1 算术运算符

    表达式 翻译为
    a + b a.plus(b)
    a - b a.minus(b)
    a * b a.times(b)
    a / b a.div(b)
    a % b a.rem(b)、 a.mod(b) (已弃用)
    a..b a.rangeTo(b)

    请注意,自 Kotlin 1.1 起支持 rem 运算符。Kotlin 1.0 使用 mod 运算符,它在 Kotlin 1.1 中被弃用。
    以下为示例:

    data class Point(val x: Int, val y: Int)
    
    operator fun Point.unaryMinus() : Point = Point(-x, -y)
    
    operator fun Point.inc(): Point = Point(x + 1, y + 1)
    
    operator fun Point.dec(): Point = Point(x - 1, y - 1)
    
    operator fun Point.plus(point: Point): Point = Point(x + point.x, y + point.y)
    
    operator fun Point.minus(point: Point): Point = Point(x - point.x, y - point.y)
    
    operator fun Point.times(point: Point): Point = Point(x * point.x, y * point.y)
    

    3.2 “in”操作符

    表达式 翻译为
    a in b b.contains(a)
    a !in b !b.contains(a)

    以下为示例代码:

    data class Point(val x: Int, val y: Int)
    
    data class Rectangle(val x: Int, val y: Int, val width: Int, val height: Int)
    
    operator fun Point.unaryMinus() : Point = Point(-x, -y)
    
    operator fun Point.inc(): Point = Point(x + 1, y + 1)
    
    operator fun Point.dec(): Point = Point(x - 1, y - 1)
    
    operator fun Point.plus(point: Point): Point = Point(x + point.x, y + point.y)
    
    operator fun Point.minus(point: Point): Point = Point(x - point.x, y - point.y)
    
    operator fun Point.times(point: Point): Point = Point(x * point.x, y * point.y)
    
    operator fun Rectangle.contains(point: Point): Boolean = point.x > x && point.x <x +width && point.y > y && point.y < y +height
    
    fun main(args: Array<String>) {
        val p = Point(1, 2)
        val rectangle = Rectangle(0, 0, 2,3)
        println(p in rectangle)  //打印true
    }
    

    3.3 索引访问操作符

    表达式 翻译为
    a[i] a.get(i)
    a[i, j] a.get(i, j)
    a[i_1, ……, i_n] a.get(i_1, ……, i_n)
    a[i] = b a.set(i, b)
    a[i, j] = b a.set(i, j, b)
    a[i_1, ……, i_n] = b a.set(i_1, ……, i_n, b)

    3.4 广义赋值

    表达式 翻译为
    a += b a.plusAssign(b)
    a -= b a.minusAssign(b)
    a *= b a.timesAssign(b)
    a /= b a.divAssign(b)
    a %= b a.remAssign(b), a.modAssign(b)(已弃用)

    通常来说,当你已经定义一个plus操作符时,Kotlin不仅仅支持+操作符,还同时支持+=操作了。重载+=操作符,除了实现plusAssign函数外,还需要函数返回值为Unit,而重载+操作符,是需要返回值的。当同时重载了+=和+操作符时,调用的时候会有编译错误,所以你只能保留一种操作符。如下:


    operator

    所以我们什么时候该用+操作符,什么时候该用+=呢?原则就是,如果你的类是一个mutable(可变化的)类,那么就使用+=操作符,反之就使用+操作符。查看源码可知MutableCollection就定义了plusAssign方法,而不是plus方法。


    plusAssign

    3.5 相等与不等操作符

    表达式 翻译为
    a == b a?.equals(b) ?: (b === null)
    a != b !(a?.equals(b) ?: (b === null))

    Kotlin判断相等跟java是有区别的。Kotlin中判断值相等是用==,而java是调用equals方法。Kotlin中判断引用相等是用===,而java使用==。在Kotlin中null==null总是true,对于非空的x,x==null总是返回false而不会调用x.equals(null)。
    当与null显示比较时,a==null会自动转换为a===null,注意:===和!==不可重载。

    3.6 Elvis操作符 ?:

    在Kotlin中,Elvis操作符特定是跟null比较。也就是说y = x?:0等价于val y = if (x!==null) x else 0。主要用于null的安全检查,Elvis操作符是一个二元运算符,如果第一个操作数不为null,则返回自己,否则返回第二个操作数。

    在Kotlin中没有java中的三元运算符true?1:0,只有类似的`if (true) 1 else 0。而Evlis操作符是精简版的三元操作符。在java中使用三元运算符通常要重复变量两次,如下:

    String name = ...;
    String displayName = name !=null ? name : "Unknown";
    

    而在Kotlin中:

    val name = ...
    val displayName = name?:"Unkown"
    

    3.7 比较操作符

    表达式 翻译为
    a > b a.compareTo(b) > 0
    a < b a.compareTo(b) < 0
    a >= b a.compareTo(b) >= 0
    a <= b a.compareTo(b) <= 0

    所有的比较都转换为对 compareTo 的调用,这个函数需要返回 Int 值。

    3.8 操作符优先级

    优先级 标题 符号
    最高 后缀(Postfix) ++, --, ., ?., ?
    前缀(Prefix) -, +, ++, --, !, labelDefinition@
    右手类型运算(Type RHS,right-hand side class type) :, as, as?
    乘除去余(Multiplicative) *, /, %
    加减(Additive) *, /, %
    区间范围(Range) ..
    infix函数 1 shl 2
    Elvis操作符 ?:
    命名检查符(Named checks) in, !in, is, !is
    比较大小(Comparison) <, >, <=, >=
    相等行判断(Equality) ==, !==
    与(Conjunction) &&
    或(Disjunction) ll
    最低 赋值(Assignment) =, +=, -=, *=, /=, %=

    4. 中缀表示法

    函数还可以用中缀表示法调用,满足下面三个条件时:

    • 他们是成员函数或扩展函数
    • 他们只有一个参数
    • 他们使用infix关键字标注
      示例:
    data class Point(var x: Int, var y: Int)
    
    data class Rectangle(val x: Int, val y: Int, val width: Int, val height: Int)
    
    operator fun Point.unaryMinus() : Point = Point(-x, -y)
    
    operator fun Point.inc(): Point = Point(x + 1, y + 1)
    
    operator fun Point.dec(): Point = Point(x - 1, y - 1)
    
    operator fun Point.plusAssign(point: Point) {
        x += point.x
        y += point.y
    
    }
    
    operator fun Point.minus(point: Point): Point = Point(x - point.x, y - point.y)
    
    operator fun Point.times(point: Point): Point = Point(x * point.x, y * point.y)
    
    operator fun Rectangle.contains(point: Point): Boolean = point.x > x && point.x <x +width && point.y > y && point.y < y +height
    
    infix fun Point.mut(point: Point): Point = Point(x * point.x, y * point.y)
    
    fun main(args: Array<String>) {
        var x = Point(1, 2)
        var y = Point(3, 6)
    
        println(x mut y)  //打印Point(x=3, y=12)
    
    }
    

    Kotlin语言基础笔记

    Kotlin流程控制语句笔记

    Kotlin操作符重载与中缀表示法笔记

    Kotlin扩展函数和扩展属性笔记

    Kotlin空指针安全(null-safety)笔记

    Kotlin类型系统笔记

    Kotlin面向对象编程笔记

    Kotlin委托(Delegation)笔记

    Kotlin泛型型笔记

    Kotlin函数式编程笔记

    Kotlin与Java互操作笔记

    相关文章

      网友评论

        本文标题:Kotlin操作符重载与中缀表示法笔记

        本文链接:https://www.haomeiwen.com/subject/ddputftx.html