为 case class 自动生成 case 对象
automatically generate case object for case class
如何让 scala 编译器自动生成 case 对象?
// Pizza class
class Pizza (val crust_type: String)
// companion object
object Pizza {
val crustType = "crust_type"
}
案例对象的所需属性
- 为
case class
中的每个属性在 case object
中生成一个属性
- 将每个对应case对象的值设置为属性名的字符串表示,将对象属性名
camelCase
改为snake_case
,对象属性保留snake_case
值
您可以创建宏注释
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
@compileTimeOnly("enable macro paradise to expand macro annotations")
class GenerateCompanion extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro GenerateCompanion.impl
}
object GenerateCompanion {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
annottees match {
case (c@q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") :: Nil =>
val vals = paramss.flatten.map(p => {
val name = p.name.toString
q"val ${TermName(underscoreToCamel(name))}: String = $name"
})
q"""
$c
object ${tpname.toTermName} {..$vals}
"""
}
}
def underscoreToCamel(name: String): String = "_([a-z\d])".r.replaceAllIn(name, _.group(1).toUpperCase)
}
并使用它
@GenerateCompanion
class Pizza(val crust_type: String)
Pizza.crustType //crust_type
新宏:
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
@compileTimeOnly("enable macro paradise to expand macro annotations")
class GenerateCompanion extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro GenerateCompanion.impl
}
object GenerateCompanion {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
def vals(paramss: Seq[Seq[ValDef]]): Seq[ValDef] =
paramss.flatten.map(p => {
val name = p.name.toString
q"val ${TermName(underscoreToCamel(name))}: String = $name"
})
annottees match {
case (c@q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") :: Nil =>
q"""
$c
object ${tpname.toTermName} {
..${vals(paramss)}
}
"""
case (c@q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") ::
q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }" :: Nil =>
q"""
$c
$mods object $tname extends { ..$earlydefns } with ..$parents { $self =>
..$body
..${vals(paramss)}
}
"""
}
}
def underscoreToCamel(name: String): String = "_([a-z\d])".r.replaceAllIn(name, _.group(1).toUpperCase)
}
用法:
@GenerateCompanion
class Pizza(val crust_type: String, val foo_foo: Int)
object Pizza {
def bar: String = "bar"
}
Pizza.crustType //crust_type
Pizza.fooFoo //foo_foo
Pizza.bar //bar
如何让 scala 编译器自动生成 case 对象?
// Pizza class
class Pizza (val crust_type: String)
// companion object
object Pizza {
val crustType = "crust_type"
}
案例对象的所需属性
- 为
case class
中的每个属性在case object
中生成一个属性
- 将每个对应case对象的值设置为属性名的字符串表示,将对象属性名
camelCase
改为snake_case
,对象属性保留snake_case
值
您可以创建宏注释
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
@compileTimeOnly("enable macro paradise to expand macro annotations")
class GenerateCompanion extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro GenerateCompanion.impl
}
object GenerateCompanion {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
annottees match {
case (c@q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") :: Nil =>
val vals = paramss.flatten.map(p => {
val name = p.name.toString
q"val ${TermName(underscoreToCamel(name))}: String = $name"
})
q"""
$c
object ${tpname.toTermName} {..$vals}
"""
}
}
def underscoreToCamel(name: String): String = "_([a-z\d])".r.replaceAllIn(name, _.group(1).toUpperCase)
}
并使用它
@GenerateCompanion
class Pizza(val crust_type: String)
Pizza.crustType //crust_type
新宏:
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
@compileTimeOnly("enable macro paradise to expand macro annotations")
class GenerateCompanion extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro GenerateCompanion.impl
}
object GenerateCompanion {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
def vals(paramss: Seq[Seq[ValDef]]): Seq[ValDef] =
paramss.flatten.map(p => {
val name = p.name.toString
q"val ${TermName(underscoreToCamel(name))}: String = $name"
})
annottees match {
case (c@q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") :: Nil =>
q"""
$c
object ${tpname.toTermName} {
..${vals(paramss)}
}
"""
case (c@q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") ::
q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }" :: Nil =>
q"""
$c
$mods object $tname extends { ..$earlydefns } with ..$parents { $self =>
..$body
..${vals(paramss)}
}
"""
}
}
def underscoreToCamel(name: String): String = "_([a-z\d])".r.replaceAllIn(name, _.group(1).toUpperCase)
}
用法:
@GenerateCompanion
class Pizza(val crust_type: String, val foo_foo: Int)
object Pizza {
def bar: String = "bar"
}
Pizza.crustType //crust_type
Pizza.fooFoo //foo_foo
Pizza.bar //bar