Scala: Example use for early definition / early in

2019-07-04 04:06发布

Scala allows you to make early definitions like so:

trait A {
  val v: Int
}

class B extends { val v = 4 } with A

What is an example use of this feature?

标签: scala traits
3条回答
何必那么认真
2楼-- · 2019-07-04 04:31

Let's see a example from the Programming in Scala book (page 451). If we have a definition like this:

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

Then numerArg and denomArg are called abstract vals & the trait can be used directly without extends, like this:

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

Or

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

The above two are both valid Pre-initializing of abstract val in trait, except that when you need to put an expression value to abstract vals, you can only use the later form, like this:

val z = new {
  val numerArg = 1 * x
  val denomArg = 2 * x
} with RationalTrait

Another interesting example in book is to Pre-initialized fields in a class definition.

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
  )
}
查看更多
时光不老,我们不散
3楼-- · 2019-07-04 04:38

In unit tests in particular, you are interested on testing traits in isolation. In this case, you need to create an Object mixed in with the trait you are interested. This is an example:

trait Display {
  def show(msg: String) = ...
}

val o = new Object with Display
o.show("hey!")

Another scenario is when your trait depends on injected variables:

trait Logging {
  val stream: java.io.OutputStream
  def log(msg: String) = ...
}

val o = new { val stream = new FileOutputStream(...) } with Logging
o.log("hey!")
查看更多
一夜七次
4楼-- · 2019-07-04 04:47

Whenever the value is used for the trait initialization. So for eaxmple for this trait:

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

The parameter is used to substitute for a constructor parameter. However the parameter should be rather made an abstract method, because it leaves more free space to the implementer.

查看更多
登录 后发表回答