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,而重载+操作符,是需要返回值的。当同时重载了+=和+操作符时,调用的时候会有编译错误,所以你只能保留一种操作符。如下:
所以我们什么时候该用+操作符,什么时候该用+=呢?原则就是,如果你的类是一个mutable(可变化的)类,那么就使用+=操作符,反之就使用+操作符。查看源码可知MutableCollection就定义了plusAssign方法,而不是plus方法。
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)
}