为什么你不能在隐式类中添加字段?
例如,下面的代码不存储originalName字段
object Implicit1 {
implicit class AI1(c: Class[_]) {
private var originalName = ""
def setOriginalName(str: String) = originalName = str
def getOriginalName=originalName
}
}
答案 0 :(得分:6)
隐式类是一个可以作为类的包装器隐式调用的类(在本例中是Class
的实例)。它绝对可以有var
;从这个意义上说,你的代码工作正常。
问题是你无法获得AI1
的实例。所以你创建它,加载var
,然后扔掉它。它不是原始c: Class[_]
实例的一部分;这里没有猴子修补。它只会让您输入(new AI1(c)).whicheverMethodYouPutOnAI1
。
如果你确实有办法获得AI1
,那么当你写完它时,你将无法再次获得c
。 AI1
不是Class[_]
的代理,只是拥有它的实例。现在你的getter和setter不会在暴露var时添加任何东西。所以你可能意味着类似
implicit class AI1(val underlying: Class[_]) {
var originalName = ""
def hasName = this
}
现在你可以做像
这样的事情val named = "fish".getClass.hasName
named.originalName = "salmon"
println(s"${named.originalName} ${named.underlying}")
答案 1 :(得分:1)
正如Rex Kerr所提到的,每次需要时都会创建隐式类。因此,每次都会获得隐式类的新实例,存储在字段中的值已丢失。
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
这是一种解决方法:
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
答案 2 :(得分:0)
概括和抽象一点我使用以下方法:
implicit class class_extension(val class_to_extend: class_to_extend) {
import class_extension._
private val fields = class_extension_fields_map.getOrElseUpdate(class_to_extend, class_extension_fields(default_value_1, default_value_2))
def a = fields.a
def a_=(value: Int) = fields.a = value
def b = fields.b
def b_=(value: Int) = fields.b = value
}
object class_extension {
private case class class_extension_fields(var a: Int, var b: Boolean)
private val class_extension_fields_map = new HashMap[class_to_extend, class_extension_fields]
}
这基本上允许在某个上下文中“扩展”类,例如将字段添加到图的 - 所有 - 节点以应用某种算法。