Scala类的字段类型是什么?

Scala类的字段类型是什么?,scala,Scala,我想编写如下函数: def printFieldOfClass(field: ???) = println(field) 假设有一个case类定义,例如case class a(id:String)。然后可以调用类(A.id)的printfield,它将打印字符串“A.id”。但是,如果我们尝试调用printFieldOfClass(A.idd),我希望代码不要编译。这可能吗?如果是,参数字段的类型是什么 非常感谢您的帮助 编辑:由于我试图做的事情似乎有些混乱,让我澄清一下:我不想传递ca

我想编写如下函数:

def printFieldOfClass(field: ???) =
  println(field)
假设有一个case类定义,例如
case class a(id:String)
。然后可以调用类(A.id)的
printfield
,它将打印字符串
“A.id”
。但是,如果我们尝试调用
printFieldOfClass(A.idd)
,我希望代码不要编译。这可能吗?如果是,参数
字段的类型是什么

非常感谢您的帮助


编辑:由于我试图做的事情似乎有些混乱,让我澄清一下:我不想传递case类的实例,我更希望传递对类定义中某个字段的引用。另外,我不希望我的函数硬连接到任何这样的类,它应该与所有Scala类一起工作,比如:
printFieldOfClass(someClasstheFunctionsNotKnowAbout.someField)
应该打印
“someClasstheFunctionsNotKnowAbout.someField”
如果
someclasses函数不知道
的定义指定了一个字段
someField
,或者,如果类没有这样的字段,调用就不应该编译。

如果类的
printfield
是一个普通方法,这是不可能的,正如注释所解释的。但您可以将其改为宏。它基本上是一个在编译时运行的函数,接收其参数的语法树并生成一个新的树来替换它。关于Scala宏有很多介绍,在答案中再写一个是没有意义的。但我不建议你尝试它,直到你对Scala总体上很满意为止

它的功能与您想要的非常接近:

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"

如果
printFieldOfClass
是一个正常的方法,这是不可能的,正如注释所解释的。但您可以将其改为宏。它基本上是一个在编译时运行的函数,接收其参数的语法树并生成一个新的树来替换它。关于Scala宏有很多介绍,在答案中再写一个是没有意义的。但我不建议你尝试它,直到你对Scala总体上很满意为止

它的功能与您想要的非常接近:

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"

如果该字段不存在,当然不会编译。如果字段存在,则函数无法知道作为参数获取的值来自何处。最后,这样做似乎毫无意义。顺便说一句,如果
A
不是一个单例,
A.field
将永远不会编译,即使类
A
上有一个field
field
,我也不明白。函数是否需要知道作为参数获取的值来自何处?你说“来自”是什么意思?想想看。该方法接收任何类型的值。它怎么可能追溯到某个类的某个字段?没有办法做到这一点,而能够做到这一点是没有意义的it@Dici在几乎所有的语言中,你都是正确的。但是Scala宏允许你这样做。如果这个字段不存在,当然它不会编译。如果字段存在,则函数无法知道作为参数获取的值来自何处。最后,这样做似乎毫无意义。顺便说一句,如果
A
不是一个单例,
A.field
将永远不会编译,即使类
A
上有一个field
field
,我也不明白。函数是否需要知道作为参数获取的值来自何处?你说“来自”是什么意思?想想看。该方法接收任何类型的值。它怎么可能追溯到某个类的某个字段?没有办法做到这一点,而能够做到这一点是没有意义的it@Dici在几乎所有的语言中,你都是正确的。但是Scala宏允许您这样做。什么是
q
?在这里找不到@JensHoffmann哦,我明白了,当然。它必须返回一个语法树,因此这用于转换。谢谢,难道不能有一个
nameOfImpl
方法吗?您的两个方法具有相同的实现和签名。什么是
q
?在这里找不到@JensHoffmann哦,我明白了,当然。它必须返回一个语法树,因此这用于转换。谢谢,难道不能有一个
nameOfImpl
方法吗?两个方法具有相同的实现和签名。