I try to get names of all trait a class extends using getInterfaces
which returns an array of trait's names. When I manually access each member of the array, the method getName
returns simple names like this
trait A
trait B
class C() extends A, B
val c = C()
val arr = c.getClass.getInterfaces
arr(0).getName // : String = A
arr(1).getName // : String = B
Run Code Online (Sandbox Code Playgroud)
However, when I use map
function on arr
. The resulting array contains a cryptic version of trait's names
arr.map(t => t.getName) // : Array[String] = Array(repl$.rs$line$1$A, repl$.rs$line$2$B)
Run Code Online (Sandbox Code Playgroud)
The goal of this question is not about how to get the resulting array that contains simple names (for that purpose, I can just use arr.map(t => t.getSimpleName)
.) What I'm curious about is that why accessing array manually and using a map
do not yield a compatible result. Am I wrong to think that both ways are equivalent?
我相信你在 Scala REPL 或 Ammonite 中运行东西。
当您定义:
trait A
trait B
class C() extends A, B
Run Code Online (Sandbox Code Playgroud)
类A
,B
并且C
未在根包的顶层定义。REPL 创建一些隔离的环境,编译代码并将结果加载到一些内部“匿名”命名空间中。
但事实并非如此。创建该字节码的位置反映在类名称中。所以显然有一些类似的东西(不一定相同)
// repl$ suggest object
object repl {
// .rs sound like nested object(?)
object rs {
// $line sounds like nested class
class line { /* ... */ }
// $line$1 sounds like the first anonymous instance of line
new line { trait A }
// import from `above
// $line$2 sounds like the second anonymous instance of line
new line { trait B }
// import from above
//...
}
}
Run Code Online (Sandbox Code Playgroud)
这是因为 REPL 中作用域的工作方式:新行创建一个新作用域,其中包含先前看到的定义和新添加的定义(可能会掩盖某些旧定义)。这可以通过创建一段新代码作为新匿名类的代码、对其进行编译、读入类路径、实例化并导入其内容来实现。通过将每个新行放入单独的类 REPL 中,可以逐步编译和运行内容,而无需等待您告诉它脚本已完成并关闭。
当您使用运行时反射访问类名时,您会看到事物评估方式的工件。一条路径可能会通过隐藏此类内容的 REPL 修饰器,而另一条路径则绕过它们,以便您看到 JVM 所看到的原始值。