使用方法为案例类生成伴随对象(字段 = 方法)

2023-12-08

使用 scala-macros 为案例类生成伴随对象

我尝试过的一些代码示例,它有效,我可以获取元组列表(名称 - >类型),但如何在同一范围内生成对象?

  import c.universe._
  val tpe = weakTypeOf[T]

  val fields = tpe.decls.collectFirst {
    case m: MethodSymbol if m.isPrimaryConstructor => m
  } .get
    .paramLists
    .head

  val extractParams = fields.map { field =>
    val name = field.asTerm.name
    val fieldName = name.decodedName.toString
    val NullaryMethodType(fieldType) = tpe.decl(name).typeSignature

    c.Expr[List[(String, String)]](
      q"""
       ($fieldName, ${fieldType.toString})
      """
    )

是否可以注释某些案例类并使生成的同伴在同一范围内可见?

// test case: defined a class with some fields
@GenerateCompanionWithFields
case class SomeCaseClass(i: Int, b: Byte, c: Char)

goal:

SomeCaseClass.i() // returns Int 
SomeCaseClass.b() // returns Byte
SomeCaseClass.c() // returns Char

您的代码似乎适用于定义宏。但是如果你想生成同伴你应该使用宏注释

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox

object Macros {
  @compileTimeOnly("enable macro paradise")
  class GenerateCompanionWithFields extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro Macro.impl
  }

  object Macro {
    def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
      import c.universe._
      annottees match {
        case (cls @ q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") :: Nil =>

          val newMethods = paramss.flatten.map {
            case q"$_ val $tname: $tpt = $_" =>
              q"def $tname(): String = ${tpt.toString}"
          }

          q"""
             $cls

             object ${tpname.toTermName} {
               ..$newMethods
             }
           """
      }
    }
  }
}

import Macros._

object App {
  @GenerateCompanionWithFields
  case class SomeCaseClass(i: Int, b: Byte, c: Char)
}

//Warning:scalac: {
//  case class SomeCaseClass extends scala.Product with scala.Serializable {
//    <caseaccessor> <paramaccessor> val i: Int = _;
//    <caseaccessor> <paramaccessor> val b: Byte = _;
//    <caseaccessor> <paramaccessor> val c: Char = _;
//    def <init>(i: Int, b: Byte, c: Char) = {
//      super.<init>();
//      ()
//    }
//  };
//  object SomeCaseClass extends scala.AnyRef {
//    def <init>() = {
//      super.<init>();
//      ()
//    };
//    def i(): String = "Int";
//    def b(): String = "Byte";
//    def c(): String = "Char"
//  };
//  ()
//}

自动生成案例类的案例对象

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用方法为案例类生成伴随对象(字段 = 方法) 的相关文章

随机推荐

  • MySQL、utf8_general_ci 和西里尔字符

    MySQL 版本 4 1 及其排序规则 utf8 general ci 似乎不喜欢特定的西里尔字符 和 适用于 MySQL 5 0 及以上版本 由于该字段用于存储俄语以外的语言 英语 爱沙尼亚语 德语 的信息 因此更改排序规则的类型是不可想
  • 在 AWS IOT 中调用 getShadow/updateShadow 时出现 ForbiddenError 403

    我有带有联合 ID 的经过身份验证的用户 但是当我尝试访问 AWS IOT 内容时 我收到了这个错误 这让我发疯 我正在关注iot sample code 所有相关凭证也都是正确的 MQTTHelper credentialsProvide
  • 重定向子进程的输出

    有多种方法可以重定向子进程的输出 using freopen 3 using dup 3 using popen 3 如果需要的话 应该选择什么是执行子进程并将其输出保存在给定文件中 非常类似于ls gt files txt works s
  • 在多页中获取 Activecontrol

    我正在尝试获取该名称Listbox我刚刚选择的 ListBox1 Caveat ListBox1位于Multipage1 在第一个选项卡上 Private Sub ListBox1 Click Dim m As String m Me Ac
  • 在 Ubuntu 14.04 上的 Python 2.6 上安装 M2Crypto 0.20.1

    我需要在 Ubuntu 14 04 上从 Python 2 6 的源代码编译并安装 M2Crypto 0 20 1 我现在无法迁移到 Python2 7 但我们正在计划这样做 我安装了Python2 6https launchpad net
  • 使用 Sass 定制引导程序;我到底应该在我的 scss 文件中导入 bootstrap 吗?

    在尝试使用 Sass 自定义引导程序时 我注意到覆盖默认引导程序变量似乎以一种不连贯的方式工作 并且希望有人可以解释到底发生了什么导致这种行为 某些变量似乎只有在导入 bootstrap 之前声明时才会被覆盖 其他变量似乎只有在导入 boo
  • 当密钥未翻译时使用默认语言后备

    我可以使用默认语言 例如英语 作为其他语言的 Localized strings 文件中的未翻译键吗 为此 您可以使用英文单词作为 Localized strings 文件中的键 另一种方法是检查 NSLocalizedString 的结果
  • 如何在悬停子元素时更改父元素的颜色

    我有一个带有社交链接的 div 当悬停任何具有不同颜色的锚点时 我想使背景颜色填充整个 div 具体取决于悬停的链接 目前 背景仅在锚文本下方发生变化 我正在研究使用纯 CSS 为整个父级填充子级背景颜色的方法 social width 4
  • JPA:如何在静态 JPA 元模型中对 NUMBER 列执行 LIKE?

    我确实有一个带有 NUMBER 实际上是 BigDecimal 不要问为什么 列的静态元模型 现在我想对该数字列进行 LIKE 查询 CriteriaBuilder cb cb like entity get Entity numberco
  • 如何链接多个 Promise?

    我不太确定 也许我错过了一些明显的东西 但我不知道如何链接两个承诺 我的基于回调的代码看起来像这样 async series function cb Create the directory if the nodir switch isn
  • 为什么 Erlang 中阶乘不会溢出堆栈?

    module demo export factorial 1 factorial 0 gt 1 factorial N gt N factorial N 1 阶乘不是尾递归 但为什么它不会溢出堆栈 我能够在没有堆栈溢出的情况下获得 100
  • 将未定义的类设为友元,然后再定义它

    交一个不认识的朋友 template
  • 一次性更改多个文件的 EOL

    Notepad 或者甚至使用其他工具 有什么方法可以自动更改行结尾一次性处理多个文件 即转换 Windows EOL 的混合 CRLF 和 UNIX EOL LF 文件全部为 Windows EOL CRLF The Replace对话框可
  • 将 printf 重定向到两个流

    我正在扩展一个现有的 C 项目 将所有信息打印到stdout with printf 我希望将此信息打印到标准输出和日志文件 如果我是原始项目的贡献者 我会替换所有printf使用我的自定义日志函数进行调用 唉 我不是 所以这是我的问题 是
  • SQL 包含问题

    谁可以给我解释一下这个 我有两个查询及其结果如下 query select from tbl where contains name he AND ca 结果集 赫兹租车 海明威的小酒馆 query select from tbl wher
  • Unity 3D/球体中的翻转法线

    我已经为我的游戏编写了这段代码 我想要的是统一翻转纹理上的法线 我有一个模型和一个纹理 希望纹理位于球体模型内部而不是外部 我想通过在翻转纹理顶部的球体内部的图像周围移动相机来创建 360 度全景效果 现在 当我第一次按下播放按钮时 它运行
  • PHP domDocument 删除子节点的子节点

    如何删除子节点的父节点 但保留所有子节点 XML 文件是这样的
  • 插入一行并避免竞争条件 (PHP/MySQL)

    我正在开发一款多人游戏 该游戏有一个类似大厅的区域 玩家可以选择要进入的 区域 大厅网关由 PHP 提供支持 而实际的游戏玩法则由一台或多台 Java 服务器处理 数据存储是MySQL 幸福之路 玩家选择一个区域并告诉大厅他想进入 大厅检查
  • 如何使用 PowerShell 导出特定的 Excel 列?

    我有一个包含多列的 Excel 我想将一些特定列导出到 xlsx文件 但它导出 Excel 的前 3 列 而不是具有特定标题的列 Host CPU usage Memory usage SourceFileDirectory C TEMP
  • 使用方法为案例类生成伴随对象(字段 = 方法)

    使用 scala macros 为案例类生成伴随对象 我尝试过的一些代码示例 它有效 我可以获取元组列表 名称 gt 类型 但如何在同一范围内生成对象 import c universe val tpe weakTypeOf T val f