如何在案例类中添加特征?

时间:2012-05-04 15:33:42

标签: scala traits

我有一个如下所示的域名模型:

case class Account(id: Int, name: String)

trait BalanceTotal {
  def balance: BigDecimal
}

我的目标是拥有一个简单,轻量级的Account案例类,然后是一个增强的类Account with BalanceTotal,它只会在执行余额计算的方法中创建(这很昂贵)。

通过这种结构,我可以静态地确保在我拥有轻量级对象时,我永远不会指望存在余额。我当然知道Option,但我希望类型检查器阻止代码使用轻量级对象,我需要富含平衡的对象,反之亦然,我不认为{ {1}}给了我那个。

无论如何,我想做的是:

Option

但是失败了:

for{ Account(id,name) <- accounts } {
  yield Account(id, name) with BalanceTotal {
    override val balance = BigDecimal(44)
  }
}

如果我尝试使用';' expected but 'with' found 代替new Account,我会:

Account

我认为它与使用案例类的voodoo有关。

我可以做我想做的事吗?

更新:经过进一步考虑,我猜这与禁止案例类继承有关。但我确实需要案例类魔术:我依赖生成的super constructor arguments cannot reference unconstructed `this` apply方法来实现我的ScalaQuery映射。

3 个答案:

答案 0 :(得分:2)

对我来说没关系:

>scala
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.
7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class Account(id: Int, name: String)

trait BalanceTotal {
  def balance: BigDecimal
}
val enrichedAccount = new Account(1, "foo") with BalanceTotal {
  override val balance = BigDecimal(44)
}

// Exiting paste mode, now interpreting.

defined class Account
defined trait BalanceTotal
enrichedAccount: Account with BalanceTotal = Account(1,foo)

答案 1 :(得分:1)

由于缺少new,您的示例无效。 Account(id, name)实际上会调用Account.apply(id, name)并返回Account,您无法调用withnew Account(id, name) with BalanceTotal被转换为匿名类,使用Account扩展BalanceTotal。希望这有助于理解您的代码无法正常工作的原因。

答案 2 :(得分:1)

你的问题不是因为而是收益。使用括号如下,它将起作用:

for ( Acount(id, name) <- accounts) yield 
  (new Account(id, name) with BalanceTotal { 
    override val balance = BigDecimal(42) 
  })