【发布时间】:2021-01-03 20:56:48
【问题描述】:
假设我有一个MyItem trait,它的伴生对象有一个apply() 函数,该函数创建一个名为SubItem 的类实例,该实例从MyItem 扩展:
import scala.reflect.runtime.{universe => ru}
trait MyItem {
import MyItem._
def num: Option[Int]
}
object MyItem {
class SubItem(val num: Option[Int]) extends MyItem
def apply(num: Option[Int]): MyItem = new SubItem(num) // creates SubItem
}
def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
val modifiedItem = MyItem(Some(11))
val theType = getTypeTag(modifiedItem).tpe
如果您打印出上面的theType,它将是MyItem。
此时如果您尝试使用reflection 修改字段num,它不会起作用,因为MyItem 有num 作为方法,而不是字段(如MyItem.SubItem):
val m = ru.runtimeMirror(modifiedItem.getClass.getClassLoader)
val numTermSymb = theType.decl(ru.TermName("num")).asTerm
val im = m.reflect(modifiedItem)
val numFieldMirror = im.reflectField(numTermSymb) // not going to work
numFieldMirror.get
numFieldMirror.set(Some(999)) // my goal, if possible
不幸的是,上面会抛出scala.ScalaReflectionException: expected a field or an accessor method symbol, you provided method num。
相反,您应该执行以下操作:
val numTermSymb = theType.decl(ru.TermName("num")).asMethod
val im = m.reflect(modifiedItem)
val numFieldMirror = im.reflectMethod(numTermSymb)
numFieldMirror() // returns `Some(11)`
但我的目标是访问扩展 MyItem 的 SubItem 类并修改其字段。如何获取MyItem 类型的实例并修改MyItem 的方法num 正在访问的MyItem.SubItem 中的字段?
【问题讨论】:
-
为什么需要这样做? runtime reflection 不鼓励使用,原因有很多。您是否完全确定您的元问题只能使用 reflection 来解决。
-
@LuisMiguelMejíaSuárez 我个人会尽可能避免使用反射。但是这种方法是我团队中的高级工程师目前正在推动的
-
听到这个消息很难过,我很确定有人会来为这个问题提供一个很好的答案,但我仍然鼓励你打开另一个描述元问题的问题,它可能会对你有所帮助说服那个“高级”使用不同的方法,或者至少它会帮助你在未来成为一个更好的开发者。
-
谢谢,我会进一步探索并告诉他我对这件事的看法
标签: scala reflection scala-reflect