scala.Enumeration.nextName 如何获取标识符文本?
How does scala.Enumeration.nextName get the identifier text?
scala.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)
而不是希望的 Val(myValue)
我需要添加什么才能使其正常工作?
nextNameOrNull
即使对于原始 Scala 也不再有效 - 因为将一系列名称传递给构造函数已被弃用和删除。
这是使用原始 scala 的 Enumeration
(不是从 scala-js 替换的)执行 2.11.2:
scala> object MyObject extends Enumeration {
| val MyValue1, MyValue2 = Value
|
| println("nextName: " + nextName)
| }
defined object MyObject
scala> MyObject
nextName: null //still null
In 2.10.x
nextName
在其中一个构造函数中使用以将名称明确指定为序列(在 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
只是一个死代码。 Scala 使用 populateNameMap()
为 nameOf
提供名称(如果未指定:
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 的描述明确指定每个值的名称。
我认为 ScalaJs 也一样,除了它没有 populateNameMap()
方法,因为 JavaScript 没有这种反射 - 所以非显式命名参数的结果是:
override def toString() =
if (name != null) name //only if you did `Value("explicitName")` somwhere inside enumeration
// Scala.js specific
else s"<Unknown name for enum field #$i of class ${getClass}>"
但是,nextNameOrNull
在 Scala 和 Scala-Js 中都死了——它总是 returns null。
在 Scala JVM 中,如果 nextNameOrNull
returns null,Enumeration
uses reflection 获取分配给 Value
的 val 的名称。
在Scala.js中,我们没有这种奢侈(没有反射支持)。因此,Scala.js 编译器 特殊情况 scala.Enumeration
,以便使用它的代码可以工作。
如果你想实现一些知道分配给它的 val
名称的方法,请查看 sbt 的 project
macro。 Scala 的枚举可以从 2.10 开始以这种方式实现,但更旧。
scala.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)
而不是希望的 Val(myValue)
我需要添加什么才能使其正常工作?
nextNameOrNull
即使对于原始 Scala 也不再有效 - 因为将一系列名称传递给构造函数已被弃用和删除。
这是使用原始 scala 的 Enumeration
(不是从 scala-js 替换的)执行 2.11.2:
scala> object MyObject extends Enumeration {
| val MyValue1, MyValue2 = Value
|
| println("nextName: " + nextName)
| }
defined object MyObject
scala> MyObject
nextName: null //still null
In 2.10.x
nextName
在其中一个构造函数中使用以将名称明确指定为序列(在 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
只是一个死代码。 Scala 使用 populateNameMap()
为 nameOf
提供名称(如果未指定:
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 的描述明确指定每个值的名称。
我认为 ScalaJs 也一样,除了它没有 populateNameMap()
方法,因为 JavaScript 没有这种反射 - 所以非显式命名参数的结果是:
override def toString() =
if (name != null) name //only if you did `Value("explicitName")` somwhere inside enumeration
// Scala.js specific
else s"<Unknown name for enum field #$i of class ${getClass}>"
但是,nextNameOrNull
在 Scala 和 Scala-Js 中都死了——它总是 returns null。
在 Scala JVM 中,如果 nextNameOrNull
returns null,Enumeration
uses reflection 获取分配给 Value
的 val 的名称。
在Scala.js中,我们没有这种奢侈(没有反射支持)。因此,Scala.js 编译器 特殊情况 scala.Enumeration
,以便使用它的代码可以工作。
如果你想实现一些知道分配给它的 val
名称的方法,请查看 sbt 的 project
macro。 Scala 的枚举可以从 2.10 开始以这种方式实现,但更旧。