3

Scala 允许您像这样进行早期定义:

trait A {
  val v: Int
}

class B extends { val v = 4 } with A

此功能的示例用法是什么?

4

3 回答 3

2

每当该值用于特征初始化时。所以对于这个特征的例子:

trait UsefulTrait {
  val parameter : Int
  private val myHelperObject = new MyExpensiveClass(parameter)
}

该参数用于替代构造函数参数。然而,参数应该是一个抽象方法,因为它为实现者留下了更多的自由空间。

于 2013-05-02T23:31:44.203 回答
2

让我们看一下《Scala 编程》一书(第 451 页)中的一个示例。如果我们有这样的定义:

trait RationalTrait {
   val numerArg: Int
   val denomArg: Int
}

然后 numerArg 和 denomArg 被称为抽象 vals & trait 可以直接使用而无需扩展,如下所示:

val x = new RationalTrait {
   val numerArg = 1
   val denomArg = 2
}

或者

val y = new {
   val numerArg = 1
   val denomArg = 1
} with RationalTrait

以上两种都是trait 中 abstract val 的有效Pre-initializing ,除了需要将表达式值放入 abstract 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
  )
}
于 2013-05-03T07:12:33.893 回答
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!")
于 2017-10-17T11:35:45.127 回答