特质是Scala中一个很重要的特性。
更灵活的接口
Scala的特质(trait)定义和class几乎相同,只是trait不能的构造不能包含参数。
trait TraitClassA {
def doSomething() {
println("call A");
}
}
trait TraitClassB {
def doSomething() {
println("call B");
}
}
在使用trait的时候,可以用extend
或者with
。with
的方式成为混入(mixin)。用户可以with任意多个特质。这会让你想起接口(Interface)。
class A extends B with TraitClassA with TraitClassB {
...
}
Trait可以看做是更灵活,更丰富的接口。和Java中接口不同的是,Trait可以包含成员和方法的实现。这样做的好处需要某个trait就拿来用,而不需要重复实现接口。trait和混入的类是正交的。
举例说明,在Java中,定义一个Rational类就需要重写多个比较的方法。
class Rational(n: Int, d: Int) {
// ...
def < (that: Rational) =
this.numer * that.denom > that.numer * this.denom
def > (that: Rational) = that < this
def <= (that: Rational) = (this < that) || (this == that)
def >= (that: Rational) = (this > that) || (this == that)
}
而如果使用trait,这些比较的方法就可以封装在Ordered这个特质中(注意到这里使用到了类型参数[Rational])。以后所有需要实现比较特质的类,它只要实现compare方法。
class Rational(n: Int, d: Int) extends Ordered[Rational] {
// ...
def compare(that: Rational) =
(this.numer * that.denom) - (that.numer * this.denom)
}
而在使用的时候,你还是可以使用>
,<=
这样的方法,因为它们已经在Ordered特质中得到了实现。
值得注意的是,Java8中也借鉴了类似的方式。现在你可以在Java的接口中定义默认的实现了。但是它的限制还是很多。对于Java8一些新特性和Scala的比较,今后会专门讲。
堆叠和线性化
在下面的例子里,我们定义了带时间戳的日志和截断过长的的日志,这两个特质。
// 带时间戳的日志
trait TimestampLogger extends Logged {
override def log (msg: String) {
super.log(new java.util.Date() + " " + msg)
}
}
// 截断过长的的日志
trait ShortLogger extends Logged {
val maxLength = 20
override def log(msg: String) {
super.log(
if (msg.length <= maxLength) msg
else msg.substring(0, maxLength - 3) + "...")
}
}
我们的应用就可以混入这两个特质。
class myApp with TimestampLogger with ShortLogger
你也许觉得trait和C++中的多继承很像。但是它们有着根本的区别。在多继承的框架里,你必须指定哪个super被调用(比如通过虚函数)。这样,在上面的例子中,只有一个log方法会调用。而trait恰恰可以堆叠多个特性,每个log都会被调用。这才符合多个特质的语义。
注意到混入是有顺序的,基本上可以认为是最右边的先调用。在更复杂的情景中,Scala使用了线性化的方式,将复杂的继承图映射到一条线上,以保障多个特质执行的顺序。
使用原则
什么时候使用特质呢?
- 不需要复用的,或者执行效率非常关键,考虑使用具体类。
- 会在多个不太相关的类中使用,考虑使用特质。
- 继承自Java的代码,或者希望Java client以后调用,使用抽象函数。
- 不太确定使用哪种方式,考虑先使用特质,以后再调整。
使用特质的一个重要原则就是保持traits简短并且是正交的。不要把分离的功能混在一个trait里,考虑将最小的相关的意图放在一起。例如,想象一下你要做一些IO的操作:
trait IOer {
def write(bytes: Array[Byte])
def read(n: Int): Array[Byte]
}
分离两个行为:
trait Reader { def read(n: Int): Array[Byte] }
trait Writer { def write(bytes: Array[Byte]) }
可以将它们以混入的方式实现一个
IOer : new Reader with Writer...
接口最小化促使更好的正交性和更清晰的模块化。
相关推荐
Scala这个名字是“Scalable Language”的缩写,它旨在克服Java的一些局限性,同时保留其平台兼容性和面向对象的基础。 在Scala-2.11.1.zip这个压缩包中,我们看到的是Scala的特定版本2.11.1。这个版本是在Scala 2.x...
通过以上步骤,你已经成功地在VSCode中创建了一个基础的Scala-SBT-Helloworld项目。随着你对Scala和sbt的理解加深,可以尝试扩展项目,添加更多的功能,或者创建自己的sbt构建脚本来满足特定需求。学习Scala不仅意味...
类和对象是构建Scala程序的基础,而特质(trait)则提供了一种灵活的继承和复用机制。函数在Scala中是第一等公民,可以作为值传递,存储在变量中,甚至作为其他函数的参数或返回值。 `2.11.1`是Scala的一个重要版本...
1. **基础语法**:Scala的基础语法与Java有很多相似之处,但也有其独特的特点,如模式匹配、高阶函数、类型推断和case类。文档会详细解释这些概念,帮助初学者快速上手。 2. **类型系统**:Scala有一个强大的静态...
2. **标准库**:Scala的标准库提供了大量的类和模块,包括集合操作、I/O、反射、并发处理等,这些是编写Scala程序的基础。 3. **Scala REPL**:Read-Eval-Print Loop,交互式解释器,允许开发者即时测试代码片段,...
7. Scala REPL(Read-Eval-Print Loop):Scala提供了交互式的命令行工具,允许开发者快速测试代码片段,加速开发过程。 8. Akka框架:虽然不是Scala语言的一部分,但Akka是一个在Scala中广泛使用的并发和分布式...
4. **库和框架**:Scala是许多流行框架的基础,如Play Framework(用于Web开发)、Apache Spark(大数据处理)和Akka(并发和分布式计算)。这些框架使得开发高效、可扩展的应用变得容易。 5. **编译器和IDE支持**...
它可能涵盖了变量声明、基本数据类型、类与对象、模式匹配、高阶函数、类型系统、特质(trait)等主题,这些都是Scala编程的基石。此外,这本书还可能深入到Akka框架的介绍,因为Akka是Scala中用于构建分布式、反应...
本节主要讲解Scala在面向对象编程方面的特性,包括包管理、类和对象、单例对象和伴生对象、特质、枚举类以及应用类。 首先,Scala的包管理类似于Java,用于组织和管理类,避免名称冲突并提供访问控制。包的命名遵循...
7. **命令行工具**:除了编译器和解释器,Scala还提供了用于构建、测试和文档生成的工具,如sbt(Scala Build Tool)的前身。 总结来说,"scala-2.7.5.final" 包含了Scala语言的文档、安装程序和核心库,为开发者...
7. **Scala与大数据**:Scala在Apache Spark等大数据框架中的应用,以及如何使用Scala进行大数据处理和分析。 这些知识点不仅涵盖了Scala语言的基础和高级特性,还深入到利用Scala进行JVM平台上的多核并行计算,为...
Scala还引入了一些独特的语言特性,如特质(Traits)、隐式转换和case类,这些帮助开发者实现更简洁、更具表达力的代码。 10. 社区与文档: Scala有一个活跃的社区,提供了丰富的开源库和工具,以及详尽的官方...
在学习Scala时,开发者还需要了解一些关键概念,比如 Trait(特质),它是Scala中的一个抽象类的变种,可以用于实现多重继承和代码重用。还有 implicits(隐式转换),它可以帮助解决类型转换的繁琐问题,同时也可...
Spark是一个分布式计算框架,最初就是用Scala编写的,因此Scala是理解和开发Spark应用的基础。Spark利用Scala的高阶函数和弹性数据结构,使得数据处理变得高效且易于编写。Spark支持批处理、交互式查询(Spark SQL)...
- **面向对象**:Scala支持类、对象和继承,同时也引入了特质(trait),提供了一种更灵活的实现多继承的方式。 - **函数式编程**:Scala内置了高阶函数和不可变数据结构,使得函数式编程风格成为可能,这对于并行...
- **继承**:Scala支持单一继承,但可以通过特质(trait)实现多重继承的效果。 - 继承层次图:通过图释11.1展示了Scala中的类继承层次。 - 类型线性化:通过表格12.1展示了类型在继承链中的线性化顺序。 #### 六、...
1. 面向对象:Scala中的所有值都是对象,它使用类和特质(trait)来定义类和对象的行为,使其成为一个纯面向对象的语言。 2. 函数式编程:Scala支持函数式编程范式,其中函数被当作一等公民(first-class citizens...
7. Play框架:Play是一个基于Scala和Java的现代Web应用框架,它采用 Reactive Model(响应式模型)设计,非常适合开发RESTful API和实时Web应用。 8. Spark框架:Apache Spark是大数据处理领域的热门框架,其核心...
在API方面,Scala的基础库非常丰富,包含了许多核心类和特质。例如,`Any`, `AnyVal`, 和 `AnyRef` 是所有Scala类型的根,`AnyVal` 包括原始类型如`Int`, `Double`, `Char`等,而`AnyRef` 类似于Java中的`Object`,...
1. **基础语法**:Scala的基础语法包括类、对象、特质、模式匹配等,这些都是函数式编程的重要工具。例如,特质(Traits)可以用于实现行为的多继承,模式匹配则提供了强大的数据解构能力。 2. **高阶函数**:Scala...