某些Scala的操作符并不总对所有参数求值,例如标准布尔操作符&&和||,这种操作符也可以是方法调用,因为Scala的参数是允许传名的。下面是一个Bool类,模拟系统内建的布尔类型。
abstract class Bool {
def && (x: => Bool): Bool
def || (x: => Bool): Bool
}
在这个类中,&&和||的形参是“=>Bool”,里面的箭头表示实际参数以未求值的状态进行传递,即参数在每一次被引用的时候才求值(也就是说这个参数实际上像一个无参数的函数一样)。
这是Bool类型的两个典型(canonical)实例:
object False extends Bool {
def && (x: => Bool): Bool = this
def || (x: => Bool): Bool = x
}
object True extends Bool {
def && (x: => Bool): Bool = x
def || (x: => Bool): Bool = this
}
从上述实现可以看出,&&(或者相应地||)操作,只有在左侧对象是True(或相应地False)的时候,右侧对象才会被求值。
如同本节所示,在Scala中可以把所有操作符定义为方法,每一个操作则是一个方法调用。为了性能需求,Scala的编译器会把参数为值类型的操作直接编译为基本操作指令,但这对于编程者是完全透明的。
在前面的例子中,Zero和Succ都继承一个类,这并不是唯一的可能性。在Scala中一个类或对象可以同时继承一个类以及若干个特征(traits),一个特征是一个抽象类,作用就是用来与其它类组合。特征有时候类似于Java中的接口,可以用于定义一套抽象方法,用于被其他类实现。但不同的是Scala的特征可以有属性以及具体方法。(traits将会在后面介绍——译注)