Adding a field to Scala case class?

≡放荡痞女 提交于 2019-12-11 04:16:52

问题


I've seen some blogs on the Pimp my Library pattern, and these seem to work well for adding behavior to classes.

But what if I have a case class and I want to add data members to it? As a case class I can't extend it (inheriting from a case class is deprecated/strongly discouraged). Will any of these pimp patterns allow me to add data to a case class?


回答1:


No - I don't see how you could make this work because the enriched instance is usually thrown away (note: newly the pimp-my-library pattern is called enrich-my-library). For example:

scala> case class X(i: Int, s: String)
defined class X

scala> implicit class Y(x: X)  {
   |     var f: Float = 0F
   |   }
defined class Y

scala> X(1, "a")
res17: X = X(1,a)

scala> res17.f = 5F
res17.f: Float = 0.0

scala> res17.f
res18: Float = 0.0

You would have to make sure you kept hold of the wrapped instance:

scala> res17: Y
res19: Y = Y@4c2d27de

scala> res19.f = 4
res19.f: Float = 4.0

scala> res19.f
res20: Float = 4.0

However, I find this not useful in practice. You have a wrapper; you're better off making this explicit




回答2:


This is not the way to do. Just a proof of possibility. With this way you can get plenty of problems.

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

case class A(i: Int)

class B(a: A){
  var s: String = ""
}

object B{
  val as = scala.collection.mutable.WeakHashMap[A, B]()
}

implicit def a2b(a: A) = B.as.getOrElseUpdate(a, new B(a))

// Exiting paste mode, now interpreting.

defined class A
defined class B
defined module B
a2b: (a: A)B

scala> val a = A(1)
a: A = A(1)

scala> a.s = "test"

scala> a.s
res0: String = test

WeakHashMap: A hash map with references to entries which are weakly reachable. Entries are removed from this map when the key is no longer (strongly) referenced. This class wraps java.util.WeakHashMap.

Note that due to case class's overridden equals method you get this funny behavior:

scala> A(2).s = "test2"

scala> A(2).s
res2: String = test2

so you should not use case class or use it with override def equals(that: Any) = this eq that.asInstanceOf[AnyRef].



来源:https://stackoverflow.com/questions/11053214/adding-a-field-to-scala-case-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!