Scala語言運算符重載完全是語法層面的小把戲,本文記錄我對Scala語言運算符重載的一些理解。
方法調用語法糖
調用方法時,Scala允許省略點號和圓括號,如下面代碼所示:
把運算符映射成單詞
對於Scala來說,運算符和普通的方法沒什麼兩樣。比如下面這個類就重載了加號和減號:
我們可以這樣使用MyInt:
var myInt = new MyInt(1)
myInt = myInt + 1
用javap或者classpy分析一下scalac編譯之後的類可以知道,+實際上被編譯成了$plus()方法,-被編譯成了$minus()方法。也就是說,下面三行代碼完全等價:
myInt = myInt + 1
myInt = myInt.+(1)
myInt = myInt.$plus(1)
多符號運算符
多符號運算符無非就是單個運算符的簡單組合而已,給MyInt添加一個多符號運算符+++,如下所示:
那麼可以這樣使用+++:
var myInt = new MyInt(1)
myInt = myInt +++ 1
反編譯MyInt.class可以知道,scalac把+++運算符編譯成了$plus$plus$plus()方法。
op=語法糖
如果一個類重載了op運算符,但是沒有重載op=,那麼Scala編譯器會把x op= y替換爲x = x op y,也就是x = x.op(y),代碼如下所示:
var myInt = new MyInt(1)
myInt += 1 // myInt = myInt + 1
綁定規則
如果運算符以冒號結束,那麼運算符會綁定(bind)到右邊的操作數,也就是說,x op: y等價於y.op:(x)。我們給MyInt增加一個+:運算符,如下所示:
那麼可以這樣使用+:運算符:
var myInt = new MyInt(1)
println(1 +: myInt) // myInt.+:(1)
一元運算符
只有四種運算符可以被定義爲一元(Unary)運算符,它們是:+、-、!、~,如下面代碼所示:
下面是示例代碼:
val myInt = new MyInt(1)
println(-myInt) // -1
println(!myInt) // 99
println(~myInt)
圓括號語法糖
如果一個類定義了apply()方法,那麼Scala提供了語法糖,讓該類的實例看起來像是函數(可以直接調用)或數組(可以按下標訪問元素)。如果類定義了update()方法,那麼就可以像數組那樣按下標賦值。比如下面的Pair類:
可以像下面這樣使用Pair類:
val xy = new Pair(Array(3, 7))
println(xy(0)) // 3
println(xy(1)) // 7
xy(0) = 11
xy(1) = 18
println(xy(0)) // 11
println(xy(1)) // 18
運算符對照表
下面是我整理出來的運算符和Scala內部名稱的對照表:
+ | $plus |
- | $minus |
* | $times |
/ | $div |
% | $percent |
& | $amp |
| | $bar |
^ | $up |
~ | $tilde |
> | $greater |
< | $less |
! | $bang |
? | $qmark |
= | $eq |
: | $colon |
@ | $at |
# | $hash |
\ | $bslash |
$ | $ |
參考資料
http://www.scala-lang.org/documentation/
http://stackoverflow.com/questions/7888944/scala-punctuation-aka-symbols-and-operators
《Programming in Scala》第二版
《Scala for the Impatient》