scala.Enumeration.nextName如何获取标识符文本?

问题描述 投票:4回答:2

[scala.Enumerator.nextNamescala.Enumerator.nextName当前读取:

.nextNameOrNull
随后调用

/** The string to use to name the next created value. */ protected var nextName: Iterator[String] = _ private def nextNameOrNull = if (nextName != null && nextName.hasNext) nextName.next() else null 以获取用于枚举中创建的项目的名称。

此代码实际上是如何实现的?

当我将其复制粘贴到一个简单的示例中:

nextNameOrNull

它打印:class MyBaseClass extends Serializable { /** The string to use to name the next created value. */ protected var nextName: Iterator[String] = _ private def nextNameOrNull = if (nextName != null && nextName.hasNext) nextName.next() else null protected final def Value(): Val = Val(nextNameOrNull) case class Val(name:String) } object MyObject extends MyBaseClass { val myValue = Value println("Hello from MyObject, myValue: " + myValue) } ,而不是希望的Hello from MyObject, myValue: Val(null)

我需要添加什么才能使其正常工作?

scala scala.js
2个回答
4
投票

在Scala JVM中,如果Val(myValue)返回null,则获取Enumeration uses reflection以获取分配给Value的val的名称。

在Scala.js中,我们没有这种奢侈感(没有反射支持)。因此,Scala.js编译器特殊情况 nextNameOrNull,以便使用它的代码可以工作。

[如果要实现一些知道分配给它的scala.Enumeration名称的方法,请查看sbt的val。从2.10开始,Scala的Enumerations可能已经实现了,但是更老了。


2
投票

project macro甚至对于原始Scala也不再起作用-因为不推荐使用并删除将名称序列传递给构造函数的方法。这是使用原始scala的project(不是scala-js中替换的代码)对2.11.2的执行:

nextNameOrNull

Enumeration中的Enumeration中,在构造函数之一内部用于显式指定名称(在scala> object MyObject extends Enumeration { | val MyValue1, MyValue2 = Value | | println("nextName: " + nextName) | } defined object MyObject scala> MyObject nextName: null //still null 中删除):

2.10.x

现在此构造函数已删除,nextName只是无效代码。 Scala使用2.11.x@deprecated("Names should be specified individually or discovered via reflection", "2.10.0") def this(initial: Int, names: String*) = { this(initial) this.nextName = names.iterator } } 提供名称(如果未指定它们:

nextName

因此,它默认使用反射。您可以按照populateNameMap()的描述为每个值明确指定名称。

我认为与ScalaJs相同,不同之处在于它没有nameOf方法,因为JavaScript没有这种反射-因此,非明确命名参数的结果是:

private def populateNameMap() {
    val fields = getClass.getDeclaredFields
    def isValDef(m: JMethod) = fields exists (fd => fd.getName == m.getName && fd.getType == m.getReturnType)

    // The list of possible Value methods: 0-args which return a conforming type
    val methods = getClass.getMethods filter (m => m.getParameterTypes.isEmpty &&
                                                   classOf[Value].isAssignableFrom(m.getReturnType) &&
                                                   m.getDeclaringClass != classOf[Enumeration] &&
                                                   isValDef(m))
    methods foreach { m =>
      val name = m.getName
      // invoke method to obtain actual `Value` instance
      val value = m.invoke(this).asInstanceOf[Value]
      // verify that outer points to the correct Enumeration: ticket #3616.
      if (value.outerEnum eq thisenum) {
        val id = Int.unbox(classOf[Val] getMethod "id" invoke value)
        nmap += ((id, name))
      }
    }
  }

但是同样,here在Scala和Scala-Js中都死了-它总是返回null。

© www.soinside.com 2019 - 2024. All rights reserved.