前言
Kotlin 允許我們為自己的類型提供預定義的一組操作符的實作。這些操作符具有固定的符号表示 (如 + 或 *)和固定的優先級。為實作這樣的操作符,我們為相應的類型(即二進制操作符左側的類型和一進制操作符的參數類型)提供了一個固定名字的成員函數或擴充函數。 重載操作符的函數需要用 operator 修飾符标記。
操作符介紹
-
一進制字首操作符
表達式 +a -> 翻譯為 a.unaryPlus()
表達式 -a -> 翻譯為 a.unaryMinus()
表達式 !a -> 翻譯為 a.not()
-
執行的步驟
1 确定a的類型
2 為接收者 T 查找一個帶有 operator 修飾符的無參函數 unaryPlus()
3 如果函數不存在或不明确,則導緻編譯錯誤;
4 如果函數存在且其傳回類型為 R,那就表達式 +a 具有類型 R;
- 使用執行個體
/**
* 表達式 +a -> 翻譯為 a.unaryPlus()
* 表達式 -a -> 翻譯為 a.unaryMinus()
* 表達式 !a -> 翻譯為 a.not()
*/
data class Point(val x: Int, val y: Int)
// 負号一進制字首符
operator fun Point.unaryMinus() = Point(-x, -y)
// 正号一進制字首符
operator fun Point.unaryPlus() = Point(+x, +y)
// !一進制字首運算符
operator fun Point.not() = Point(x,y)
fun main() {
val p1 = Point(12, 24)
println(-p1)
println(!p1)
}
-
遞增和遞減
表達式 a++ -> 翻譯為 a.inc()
表達式 a-- -> 翻譯為 a.dec()
-
執行的步驟
編譯器執行以下步驟來解析字尾形式的操作符,例如 a++:
确定 a 的類型,令其為 T;
查找一個适用于類型為 T 的接收者的、帶有 operator 修飾符的無參數函數 inc();
檢測函數的傳回類型是 T 的子類型。
計算表達式的步驟是:
把 a 的初始值存儲到臨時存儲 a0 中;
把 a.inc() 結果指派給 a;
把 a0 作為表達式的結果傳回。
對于 a–,步驟是完全類似的。
對于字首形式 ++a 和 --a 以相同方式解析,其步驟是:
把 a.inc() 結果指派給 a;
把 a 的新值作為表達式結果傳回。
- 使用執行個體
/***
* 遞增運算符 ++point 會把新的結果傳回
* 遞增運算符 point++ 會把新的結果存儲在一個變量中
*/
operator fun Point.inc() = Point(x + 1, y + 1)
/**
* 遞減運算符 --point 會把新的結果傳回
* 遞增運算符 point++ 會把新的結果存儲在一個變量中
*/
operator fun Point.dec() = Point(x - 1, y - 1)
fun main() {
var p1 = Point(12, 24)
p1 = ++p1
var p2 = p1++
println(p1)
println(p2)
}
- 二進制操作符
表達式 | 翻譯為 |
---|---|
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…b | a.rangTo(b) |
- 使用執行個體
/***
* 重載 + 這個運算符
*/
operator fun String.plus(s:String) = this+s
/***
* 重載 — 這個運算符
*/
operator fun String.minus(s:String) = this+ "減号運算符的重載"+s
fun main() {
var s = "栾小黑"
var ss = s+" hello world"
var sss = s-"helloworld"
println(ss)
println(sss)
}
對應的運算符對應的方法可以在官網上看到,運算符的重載最重要的是一個關鍵在 operator的使用