1. 程式人生 > >探索Scala(1)-- 運算子過載

探索Scala(1)-- 運算子過載

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》