Why you can not add a field to the implicit class?
for example the below code does not store the originalName field
object Implicit1 {
implicit class AI1(c: Class[_]) {
private var originalName = ""
def setOriginalName(str: String) = originalName = str
def getOriginalName=originalName
}
}
An implicit class is a class that can be implicitly invoked as a wrapper for your class (in this case an instance of Class
). It absolutely can have a var
; your code works fine in that sense.
The problem is that you have no way to get an instance of AI1
. So you create it, load up the var
, and then throw it away. It's not part of the original c: Class[_]
instance; there's no monkey-patching going on here. It just saves you typing (new AI1(c)).whicheverMethodYouPutOnAI1
.
And if you did have a way to get an AI1
, you wouldn't be able to get c
again as you've written it. AI1
is not a proxy for Class[_]
, it just holds an instance of it. And right now your getter and setter don't add anything over just exposing the var. So you perhaps meant something like
implicit class AI1(val underlying: Class[_]) {
var originalName = ""
def hasName = this
}
Now you can do things like
val named = "fish".getClass.hasName
named.originalName = "salmon"
println(s"${named.originalName} ${named.underlying}")
As Rex Kerr mentioned, the implicit class will be created every time when need. Hence you will get a new instance of the implicit class every time, the value stored in the field has lost.
scala> val clz = "str".getClass
clz: Class[_ <: String] = class java.lang.String
scala> val impA: AT1 = clz
impA: Imp.AT1 = Imp$AT1@2d96543c
scala> val impB: AT1 = clz
impB: Imp.AT1 = Imp$AT1@7a560583
scala> impA == impB
res2: Boolean = false
Here is a workaround:
scala> :paste
// Entering paste mode (ctrl-D to finish)
object Imp {
object AT1 {
val clzBuffer = collection.mutable.Buffer[Class[_]]()
val strBuffer = collection.mutable.Buffer[String]()
def setName(clz: Class[_], name: String): Unit = {
val ind = clzBuffer indexWhere (_ eq clz)
if(ind == -1) {
clzBuffer += clz
strBuffer += name
}
else {
strBuffer(ind) = name
}
}
def getName(clz: Class[_]): String = {
val ind = clzBuffer indexWhere (_ eq clz)
if(ind == -1) "" else strBuffer(ind)
}
}
implicit class AT1(c: Class[_]) {
def originalName: String = AT1.getName(c)
def originalName_=(name: String) = AT1.setName(c, name)
}
}
// Exiting paste mode, now interpreting.
defined object Imp
scala> import Imp._
import Imp._
scala> val clz = "str".getClass
clz: Class[_ <: String] = class java.lang.String
scala> clz.originalName
res0: String = ""
scala> clz.originalName = "IamHere"
clz.originalName: String = IamHere
scala> clz.originalName
res1: String = IamHere
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With