加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在Scala Reflection中,为什么构造函数params会隐藏getter?

发布时间:2020-12-16 18:55:52 所属栏目:安全 来源:网络整理
导读:scala类中的变量自动获取getter你可以通过成员通过scala反射看到的setters import scala.reflect.runtime.{universe = ru}class A(var x: Int)scala ru.typeOf[A].members.filter{_.name.toString.contains("x")}res22: Iterable[reflect.runtime.universe.S
scala类中的变量自动获取getter&你可以通过成员通过scala反射看到的setters

import scala.reflect.runtime.{universe => ru}
class A(var x: Int)

scala> ru.typeOf[A].members.filter{_.name.toString.contains("x")}
res22: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(variable x,method x_=,method x)

但是,如果您创建一个子类,它在构造函数中重用了var名称,那么getter就会消失:

class B(x:Int,var y: Int) extends A(x)
scala> ru.typeOf[B].members.filter{_.name.toString.contains("x")}
res23: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(value x,method x_=)
scala> res23.head.asTerm.isVal
res25: Boolean = true

这似乎有点误导……毕竟,B仍然有一个x的吸气剂(而不是一个val)

scala> val b = new B(5,6)
b: B = B@270288ed

scala> b.x
res26: Int = 5

scala> b.x = 7
b.x: Int = 7

scala> b.x
res27: Int = 7

如果我试图假装从成员获得的值x是一个getter,我会收到一个错误:

scala> val xGetter = res23.head.asTerm
xGetter: reflect.runtime.universe.TermSymbol = value x

scala> val objMirror = ru.runtimeMirror(getClass.getClassLoader).reflect(b)
objMirror: reflect.runtime.universe.InstanceMirror = instance mirror for B@270288ed

scala> val getterMirror = objMirror.reflectField(xGetter)
scala.ScalaReflectionException: Scala field x isn't represented as a Java field,neither it has a Java accessor method
note that private parameters of class constructors don't get mapped onto fields and/or accessors,unless they are used outside of their declaring constructors.

这里有什么正确的解决方法?具有子类名称,其构造函数args与父args中的名称相同是完全错误的吗?或者不是打电话给会员,我是否需要在所有超级课程中工作以获得所有的乐趣. setter方法?

请注意,只要子类不创建具有相同名称的构造函数,成员就会为我提供继承的getter:

class Y(var x: Int)
class Z(q:Int,z: Int) extends Y(q)
scala> ru.typeOf[Z].members.filter{_.name.toString.contains("x")}
res28: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(method x_=,method x)

编辑
如果不清楚,我真的在问:
1)这是scala反射中的一个错误吗?
2)如果没有,我应该:
(a)从来没有类使用构造函数字段的名称与基类中的字段名称相同? (如果是这样,我可能会错误地定义我的所有课程…)
要么
(b)获得所有吸气剂和setters,我应该只浏览所有父类的列表并使用声明,而不是依靠成员做正确的事情,因为它在这种情况下不起作用?

编辑2
为了回应@ som-snytt的回答,x的可见方法实际上是在A中的x,而不是构造函数中的参数.

class A(var x: Int){def showMeX {println(x)}}
class B(x:Int,var y: Int) extends A(x)
scala> val b = new B(5,10)
scala> b.showMeX
5
scala> b.x = 17
b.x: Int = 17
scala> b.showMeX
17

所以我并不认为从普通用户代码的角度来看,x的getter或setter都被遮蔽了.它只被反射代码遮蔽了……对我来说没有任何意义,它会有两种不同版本的阴影.

解决方法

2) if not,should I: (a) never have classes use names of constructor fields be the same as the name of fields in base classes?

因为他们不会让我解决这个问题,这正是我所做的.我尝试给所有构造函数参数赋予与所有继承名称不同的新名称.这是编译器中的典型示例.

class PackageClassSymbol protected[Symbols] (owner0: Symbol,pos0: Position,name0: TypeName)

是的,这太荒谬了.

> https://groups.google.com/forum/#!topic/scala-language/9jLsT_RRQR0
> https://issues.scala-lang.org/browse/SI-3194
> https://issues.scala-lang.org/browse/SI-4762
> https://issues.scala-lang.org/browse/SI-6880

哦,小伙子,不要继续拉那个线程……

> https://issues.scala-lang.org/browse/SI-7475
> https://issues.scala-lang.org/browse/SI-2568
> https://issues.scala-lang.org/browse/SI-6794

不难看出任何一个被解决的几率为零.这是我退出原因的一个完美例子.

顺便说一句,如果你使用-Xlint,它就会警告你.这在SI-4762中提到过.

% cat a.scala
class A(var x: Int)
class B(x:Int,var y: Int) extends A(x) {
  def z = x
}

% scalac -Xlint a.scala
a.scala:3: warning: private[this] value x in class B shadows mutable x inherited from class A.
Changes to x will not be visible within class B - you may want to give them distinct names.
  def z = x
          ^
one warning found

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读