【问题标题】:Get all fields from anonymous class in Scala从Scala中的匿名类中获取所有字段
【发布时间】:2016-03-04 16:24:19
【问题描述】:

我想通过反射从类实例中获取所有字段。对于普通类来说一切正常(例如仅过滤器):

scala> import scala.reflect.runtime.universe._
scala> import scala.reflect.runtime.currentMirror
scala> class A {val a = 1}
scala> currentMirror.classSymbol((newA).getClass).toType.members.filter(_.name.toString == "a")
res12: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(value a)

但是对于匿名类我有不同的情况:

scala> trait B {val b = 2}
scala> currentMirror.classSymbol((new B {}).getClass).toType.members.filter(_.name.toString == "b")
res13: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(method b, value b)

这个值不是公开的,但是方法是公开的。有人可以解释一下,这里发生了什么吗?为什么在匿名课程的情况下我没有简单的公共value b?统一成员处理有什么解决方法吗?

编辑

实际上,我最初的任务是从任何实例中获取所有公共字段。如果是普通类,我使用以下代码:

val reflectedInstance = currentMirror.reflect(instance)
for {
  member ← reflectedInstance.symbol.toType.members
  if member.isPublic && (!member.isMethod || member.asMethod.isGetter)
} yield //do something

上面的示例描述了为什么此代码在匿名类的情况下不起作用。所以,现在我正在寻找某种方法,如何从普通类和匿名类中获取所有公共字段。

【问题讨论】:

    标签: scala reflection anonymous-class


    【解决方案1】:

    据我了解,您抱怨使用 method bvalue b 来表示 trait 而不是单个 value b

    您正在观察的method b 实际上是由scalac 生成的b 的抽象setter 方法。 如果 val 在类本身内部定义,则不会生成它,但只有在 trait 中定义 val 时才会生成。

    为什么他们需要val b 实际上是final(不可变)的setter? 下面的例子展示了它是如何工作的。 为一个特征生成的接口和抽象类。 抽象类使用这个 setter 来设置默认值,但同时在接口中有抽象 b 允许我们在其他类中覆盖它。

      class B1 {val b = 2}
      trait B2 {val b = 2}
      class B22 extends B2
    
    
    // decompile...
    
    public class B1
    {
      private final int b = 2;
    
      public int b() { 
      return this.b;
      }
    }
    
    
    
    public abstract interface B2
    {
      public abstract void com$db$itrac$summit$service$B2$_setter_$b_$eq(int paramInt);
    
      public abstract int b();
    }
    
    public abstract class B2$class
    {
      public static void $init$(B2 $this)
      {
        $this.com$db$itrac$summit$service$B2$_setter_$b_$eq(2);
      }
    }
    

    【讨论】:

    • 感谢您的回答。我在我的问题中添加了更多信息。我现在的主要问题是value b 不公开。
    • @LMnet 您做出了错误的假设。它是公开的!您对方法验证的第二个条件给出了错误。原因是我提供的反编译代码。
    • 你可以自己检查,那个值b是不公开的。只需在我上一个 scala repl 示例中添加 .filter(_.isPublic) 即可。正如我之前所说,隐式 setter 是公开的,但值不是。
    【解决方案2】:

    首先,如果需要,您可以使用 _.ismethod 过滤掉方法

    来自the scala docs:“特征用于通过指定支持的方法的签名来定义对象类型”

    This 回答澄清说“特征只能访问受隐式 getter 和 setter 保护的公共字段”。 (我相信这叫统一访问)

    这意味着当您声明匿名类时,val 有一个隐式 get 方法(注意 'val 没有 setter 方法,因为它们是不可变的)。

    【讨论】:

      猜你喜欢
      • 2020-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 2014-11-11
      • 1970-01-01
      相关资源
      最近更新 更多