操作符(OPERATORS)
在 Scala 中,操作符也是方法。任何具有单个参数的方法都可以被作为中缀运算符(infix operator)。例如, +
可以用点表示法调用。
10.+(1)
但是,作为中缀运算符(infix operator)读起来更容易:
10 + 1
定义和使用操作符
你可以使用任何合法的标识符作为操作符。这包括类似的名称 add
或符号 +
。
case class Vec(val x: Double, val y: Double) {
def +(that: Vec) = new Vec(this.x + that.x, this.y + that.y)
}
val vector1 = Vec(1.0, 1.0)
val vector2 = Vec(2.0, 2.0)
val vector3 = vector1 + vector2
vector3.x // 3.0
vector3.y // 3.0
类 Vec
有一个 +
方法 ,我们使用 +
方法将 vector1
和 vector2
相加。
通过使用圆括号,你可以用可读的语法构建复杂的表达式。这里定义了类 MyBool
,其中包括 add
和 or
方法:
case class MyBool(x: Boolean) {
def and(that: MyBool): MyBool = if (x) that else this
def or(that: MyBool): MyBool = if (x) this else that
def negate: MyBool = MyBool(!x)
}
现在可以使用 add 和 or 作为中缀表达式(infix operators):
def not(x: MyBool) = x.negate
def xor(x: MyBool, y: MyBool) = (x or y) and not(x and y)
这有助于使 xor
定义更加地具有可读性。
优先权
当一个表达式使用多个操作符时,操作符会基于第一个字符的优先级进行评估:
(下面没有显示字符)
* / %
+ -
:
= !
< >
&
^
|
(全部字母)
这个优先级应用在你定义的函数中。例如,接下来的表达式:
a + b ^? c ?^ d less a ==> b | c
相当于
((a + b) ^? (c ?^ d)) less ((a ==> b) | c)
?^
具有最高优先级,因为它开始于字符 ?
, +
具有第二高优先级,紧接着是 ^?
,==>
, |
和 less
。
by-name 参数(BY-NAME PARAMETERS)
By-name 参数仅当被使用时才被评估。它们与 by-value 参数相反。若要创建一个名为 by-name 的参数,只需用 =>
预置为它的类型。
def calculate(input: => Int) = input * 37
By-name 参数具有优点,如果它们在函数体中没有被使用,那它们不会被评估。另一方面,by-value 参数具有只评估一次的优点。
以下是我们如何实现 while 循环的例子:
def whileLoop(condition: => Boolean)(body: => Unit): Unit =
if (condition) {
body
whileLoop(condition)(body)
}
var i = 2
whileLoop (i > 0) {
println(i)
i -= 1
} // prints 2 1
方法 whileLoop
使用多个参数列表获取循环条件和循环体。如果 condition
为 true
,则 body
被评估然后递归调用 whileLoop
。如果 condition
为 false
,由于我们对 body
类型预置了 =>
,所以 body
不会被评估。
现在当我们传入 i > 0
作为我们的 condition
并且 println(i); i-= 1
作为方法体时,它的表现类似于许多语言中标准的 while
循环。
如果参数在计算密集地情况下进行评估或运行较长时间的代码块(如获取 URL),这种延迟评估参数直到它被使用时的能力可以帮助提高性能。