Scala提供了算術操作(Arithmetic operation)、關係操作(Rational operation)、邏輯操作(Logical operation)、位元操作(Bitwise operation)等對物件的基本操作。
- 算術操作:如+、-、*、/、%
- 關係操作:如>、>=、<、<=、==、!=
- 邏輯操作:如&&、||、!
- 位元操作:如&、|、~、^、>>、>>>、<<
- 指定操作:如+=、-=、*=、/=、%=、&=、|=、~=、>>=、>>>=、<<=
這些操作一般稱之為運算子(Operator),以下是一些實際運用:
scala> 1 + 2
res0: Int = 3
scala> 3 - 1
res1: Int = 2
scala> 3 * 10
res2: Int = 30
scala> 1 >= 2
res3: Boolean = false
scala> 1 | 2
res4: Int = 3
scala>
res0: Int = 3
scala> 3 - 1
res1: Int = 2
scala> 3 * 10
res2: Int = 30
scala> 1 >= 2
res3: Boolean = false
scala> 1 | 2
res4: Int = 3
scala>
是的,表面上看起來,這些操作確實就像是運算子,不過,Scala技術上而言,並沒有所謂的運算子,你所看到的+、-、*'、/等操作,其實都是物件上的方法,下面的示範可以印證:
scala> (1).+(2)
res5: Int = 3
scala> (3).-(1)
res6: Int = 2
scala> (3).*(10)
res7: Int = 30
scala> (1).>=(2)
res8: Boolean = false
scala> (1).|(2)
res9: Int = 3
scala>
res5: Int = 3
scala> (3).-(1)
res6: Int = 2
scala> (3).*(10)
res7: Int = 30
scala> (1).>=(2)
res8: Boolean = false
scala> (1).|(2)
res9: Int = 3
scala>
在Int物件上,定義了+、-、*、/等各個方法,上面的例子中,使用了方法的操作方式加以印證,在Scala中,物件要呼叫方法時,點(.)字元並非必要,且若方法只帶一個參數或不帶參數,則括號也可以省略。所以使得+、-、*、/等操作,形式上看來就像一般程式語言中的運算子。
所以,你也可以如下操作物件上的一些方法:
scala> val x = 1L
x: Long = 1
scala> val y: Int = x toInt
y: Int = 1
scala> "abc" toUpperCase
res11: java.lang.String = ABC
scala> "abc" indexOf 'b'
res12: Int = 1
scala>
x: Long = 1
scala> val y: Int = x toInt
y: Int = 1
scala> "abc" toUpperCase
res11: java.lang.String = ABC
scala> "abc" indexOf 'b'
res12: Int = 1
scala>
所以,你可以讓任何方法看來就像運算子,這是Scala支援語言擴充性的一種方式,在定義類別時,也可以定義+、-、*、/等方法,讓物件支援這些運算。
對於1+2這樣的操作,+是1物件上的方法名稱,從+來看,1與2是它的運算元,如果就一般程式語言來說,+是二元運算子。但對於~這樣的操作,是擺在某個數值或物件之前的運算,該如何於物件上定義方法呢?
Scala使用「unary_」作為這種前置運算的方法名稱前置,例如若要定義~這樣的運算,則在定義類別時定義「unary_~」這樣的方法名稱,當你呼叫~2,實際上等於呼叫(2).unary_~:
scala> ~2
res15: Int = -3
scala> (2).unary_~
res16: Int = -3
scala>
res15: Int = -3
scala> (2).unary_~
res16: Int = -3
scala>
不過,Scala限制可以作為前置運算的符號,只有+、-、!與~可以作為前置運算,如果你定義其它的符號,例如定義了unary_#,你仍然可以使用x.unary_#的方式呼叫(x參考至物件),但#x這樣的前置運算則是不行的(Scala的將之解釋為#.x)。