1.操作符重載
操作符重載在java中并沒有這樣的概念饵逐,它可以讓我們?yōu)橹付ǖ念愋吞峁╊A(yù)定義的一組操作符實(shí)現(xiàn)。這些操作符具有固定的符號表示(如+嚷辅、* 或 in)和固定的優(yōu)先級。怎樣實(shí)現(xiàn)操作符重載呢缤底?其實(shí)只要你實(shí)現(xiàn)一個(gè)固定名稱的函數(shù),然后用operator
來修飾這個(gè)函數(shù)番捂。查看Kotlin源碼可以發(fā)現(xiàn)有大量的操作符重載的實(shí)現(xiàn),我們來看看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 一元前綴操作符
表達(dá)式 | 翻譯為 |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
當(dāng)編譯器處理+a
時(shí)设预,它執(zhí)行以下步驟:
- 確定a實(shí)例的類型,如果類似為T犁河。
- 在T類型中查找一個(gè)帶有
operator
修飾符的無參函數(shù)unaryPlus()
鳖枕,可以是成員函數(shù)或者擴(kuò)展函數(shù)。 - 如果沒有找到桨螺,則會(huì)發(fā)生編譯錯(cuò)誤宾符。
下面代碼展示下如何實(shí)現(xiàn)一個(gè)一元減運(yùn)算符的示例:
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 遞增與遞減
表達(dá)式 | 翻譯為 |
---|---|
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 算術(shù)運(yùn)算符
表達(dá)式 | 翻譯為 |
---|---|
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 運(yùn)算符魏烫。Kotlin 1.0 使用 mod 運(yùn)算符,它在 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”操作符
表達(dá)式 | 翻譯為 |
---|---|
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 索引訪問操作符
表達(dá)式 | 翻譯為 |
---|---|
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 廣義賦值
表達(dá)式 | 翻譯為 |
---|---|
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)(已棄用) |
通常來說哄褒,當(dāng)你已經(jīng)定義一個(gè)plus操作符時(shí),Kotlin不僅僅支持+操作符煌张,還同時(shí)支持+=操作了呐赡。重載+=操作符,除了實(shí)現(xiàn)plusAssign函數(shù)外骏融,還需要函數(shù)返回值為Unit链嘀,而重載+操作符,是需要返回值的档玻。當(dāng)同時(shí)重載了+=和+操作符時(shí)怀泊,調(diào)用的時(shí)候會(huì)有編譯錯(cuò)誤,所以你只能保留一種操作符窃肠。如下:
所以我們什么時(shí)候該用+操作符包个,什么時(shí)候該用+=呢?原則就是冤留,如果你的類是一個(gè)mutable(可變化的)類碧囊,那么就使用+=操作符,反之就使用+操作符纤怒。查看源碼可知MutableCollection就定義了plusAssign方法糯而,而不是plus方法。
3.5 相等與不等操作符
表達(dá)式 | 翻譯為 |
---|---|
a == b | a?.equals(b) ?: (b === null) |
a != b | !(a?.equals(b) ?: (b === null)) |
Kotlin判斷相等跟java是有區(qū)別的泊窘。Kotlin中判斷值相等是用==熄驼,而java是調(diào)用equals方法像寒。Kotlin中判斷引用相等是用===,而java使用==瓜贾。在Kotlin中null==null總是true诺祸,對于非空的x,x==null總是返回false而不會(huì)調(diào)用x.equals(null)祭芦。
當(dāng)與null顯示比較時(shí)筷笨,a==null會(huì)自動(dòng)轉(zhuǎn)換為a===null,注意:===和!==不可重載龟劲。
3.6 Elvis操作符 ?:
在Kotlin中胃夏,Elvis操作符特定是跟null比較。也就是說y = x?:0
等價(jià)于val y = if (x!==null) x else 0
昌跌。主要用于null的安全檢查仰禀,Elvis操作符是一個(gè)二元運(yùn)算符,如果第一個(gè)操作數(shù)不為null蚕愤,則返回自己答恶,否則返回第二個(gè)操作數(shù)。
在Kotlin中沒有java中的三元運(yùn)算符true?1:0
审胸,只有類似的`if (true) 1 else 0亥宿。而Evlis操作符是精簡版的三元操作符。在java中使用三元運(yùn)算符通常要重復(fù)變量兩次砂沛,如下:
String name = ...;
String displayName = name !=null ? name : "Unknown";
而在Kotlin中:
val name = ...
val displayName = name?:"Unkown"
3.7 比較操作符
表達(dá)式 | 翻譯為 |
---|---|
a > b | a.compareTo(b) > 0 |
a < b | a.compareTo(b) < 0 |
a >= b | a.compareTo(b) >= 0 |
a <= b | a.compareTo(b) <= 0 |
所有的比較都轉(zhuǎn)換為對 compareTo 的調(diào)用烫扼,這個(gè)函數(shù)需要返回 Int 值。
3.8 操作符優(yōu)先級
優(yōu)先級 | 標(biāo)題 | 符號 |
---|---|---|
最高 | 后綴(Postfix) | ++, --, ., ?., ? |
前綴(Prefix) |
- , + , ++ , -- , ! , labelDefinition @
|
|
右手類型運(yùn)算(Type RHS碍庵,right-hand side class type) | :, as, as? | |
乘除去余(Multiplicative) | *, /, % | |
加減(Additive) | *, /, % | |
區(qū)間范圍(Range) | .. | |
infix函數(shù) | 1 shl 2 | |
Elvis操作符 | ?: | |
命名檢查符(Named checks) | in, !in, is, !is | |
比較大杏称蟆(Comparison) | <, >, <=, >= | |
相等行判斷(Equality) | ==, !== | |
與(Conjunction) | && | |
或(Disjunction) | ll | |
最低 | 賦值(Assignment) | =, +=, -=, *=, /=, %= |
4. 中綴表示法
函數(shù)還可以用中綴表示法調(diào)用,滿足下面三個(gè)條件時(shí):
- 他們是成員函數(shù)或擴(kuò)展函數(shù)
- 他們只有一個(gè)參數(shù)
- 他們使用
infix
關(guān)鍵字標(biāo)注
示例:
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)
}