Scala类的字段类型是什么?

时间:2016-08-14 18:26:11

标签: scala

我想编写如下函数:

def printFieldOfClass(field: ???) =
  println(field)

假设有一个案例类定义,例如case class A(id: String)。然后可以调用printFieldOfClass(A.id)来打印字符串"A.id"。但是,如果我们尝试调用printFieldOfClass(A.idd),我希望代码不要编译。这甚至可能吗?如果是这样,参数的类型是什么field

非常感谢帮助!

编辑:由于对我要做的事情似乎有些困惑,让我澄清一下:我想传递案例类的实例 ,我更愿意在类定义中传递对某些字段的引用。此外,我不希望我的函数硬连线到任何这样的类,它应该适用于所有Scala类,如下所示:printFieldOfClass(SomeClassTheFunctionDoesNotKnowAbout.someField)应该打"SomeClassTheFunctionDoesNotKnowAbout.someField"以防SomeClassTheFunctionDoesNotKnowAbout&#39 ; s定义指定字段someField,或者,如果类没有这样的字段,则调用不应该编译。

1 个答案:

答案 0 :(得分:2)

如果printFieldOfClass是正常方法,这是不可能的,正如评论所解释的那样。但你可以把它变成一个宏。它基本上是一个在编译时运行的函数,接收其参数的语法树并生成一个新树来替换它。 Scala宏有很多介绍,在答案中写另一个没有意义。但是我不建议尝试它,直到你对Scala一般都很满意。

An example做了一些接近你想要的事情:

import scala.annotation.tailrec
import scala.language.experimental.macros
import scala.reflect.macros.blackbox

object Macros {
  def nameOfImpl(c: blackbox.Context)(x: c.Tree): c.Tree = {
    import c.universe._

    @tailrec def extract(x: c.Tree): String = x match {
      case Ident(TermName(s)) => s
      case Select(_, TermName(s)) => s
      case Function(_, body) => extract(body)
      case Block(_, expr) => extract(expr)
      case Apply(func, _) => extract(func)
    }

    val name = extract(x)
    q"$name"
  }
  def nameOfMemberImpl(c: blackbox.Context)(f: c.Tree): c.Tree = nameOfImpl(c)(f)

  def nameOf(x: Any): String = macro nameOfImpl
  def nameOf[T](f: T => Any): String = macro nameOfMemberImpl
}

//
// Sample usage:
//

val someVariable = ""
Macros.nameOf(someVariable) // "someVariable"

def someFunction(x: Int): String = ???
Macros.nameOf(someFunction _) // "someFunction"

case class SomeClass(someParam: String)
val myClass = SomeClass("")
Macros.nameOf(myClass.someParam) // "someParam"

// without having an instance of the class:
Macros.nameOf[SomeClass](_.someParam) // "someParam"