Scala允许您像这样进行早期定义:
trait A {
val v: Int
}
class B extends { val v = 4 } with A
此功能的示例用法是什么?
答案 0 :(得分:2)
每当该值用于特征初始化时。因此,对于这个特性的eaxmple:
trait UsefulTrait {
val parameter : Int
private val myHelperObject = new MyExpensiveClass(parameter)
}
该参数用于替换构造函数参数。但是,参数应该是一个抽象方法,因为它为实现者留下了更多的自由空间。
答案 1 :(得分:2)
让我们看一下 Scala中的编程一书(第451页)中的示例。如果我们有这样的定义:
trait RationalTrait {
val numerArg: Int
val denomArg: Int
}
然后numerArg和denomArg被称为抽象vals&特征可以直接使用而不需要扩展,如下所示:
val x = new RationalTrait {
val numerArg = 1
val denomArg = 2
}
或
val y = new {
val numerArg = 1
val denomArg = 1
} with RationalTrait
以上两个都是有效的预初始化的特征中的抽象val,除了,当你需要将表达式值放到抽象的val时,你只能使用后面的格式,如下所示:
val z = new {
val numerArg = 1 * x
val denomArg = 2 * x
} with RationalTrait
本书中另一个有趣的例子是类定义中的预初始化字段。
class RationalClass(n: Int, d: Int) extends {
val numerArg = n
val denomArg = d
} with RationalTrait {
def + (that: RationalClass) = new RationalClass(
numer * that.denom + that.numer * denom,
denom * that.denom
)
}
答案 2 :(得分:0)
特别是在单元测试中,您有兴趣单独测试特征。在这种情况下,您需要创建一个与您感兴趣的特征混合的对象。这是一个例子:
trait Display {
def show(msg: String) = ...
}
val o = new Object with Display
o.show("hey!")
另一种情况是你的特质取决于注入的变量:
trait Logging {
val stream: java.io.OutputStream
def log(msg: String) = ...
}
val o = new { val stream = new FileOutputStream(...) } with Logging
o.log("hey!")