【问题标题】:Are scala reflection API Names or Symbols adequate for use inside transfer objects?scala 反射 API 名称或符号是否足以在传输对象中使用?
【发布时间】:2013-10-14 09:02:35
【问题描述】:

简介

我正在开发一个用 Scala 编写的 API。我使用数据传输对象 (DTO) 作为传递给 API 函数的参数。 DTO 将由 API 的用户实例化。

由于 API 非常抽象/通用,我想指定 API 应该操作的对象的属性。示例:

case class Person(name: String, birthdate: Date)

Person "P" 的实例被传递给 API 时,API 需要知道它应该操作的 "P" 的属性:只是 namebirthdate,或两者兼而有之。

所以我需要设计一个 DTO,其中包含“P”本身的实例、某种属性声明以及关于“P”类型的附加信息。

基于字符串的方法

一种方法是使用Strings 来指定“P”的属性以及它的类型。这将相对简单,因为Strings 非常轻巧且众所周知。由于包、类型和成员的正式符号为Strings,因此声明将在一定程度上结构化。 另一方面,必须验证String-声明,因为用户可能传递无效的Strings。我可以想象用专用类型而不是 String 来表示属性的类型,这可能具有增加结构的好处,甚至可能这些类型都被设计为只有有效的实例才能存在。

反射 API 方法

当然,我想到了反射 API,我正在尝试用反射 API 之外的类型声明属性。不幸的是,scala 2.10.x 反射 API 有点不直观。名称、符号、镜像、类型、类型标签可能会引起一些混乱。

基本上我看到Strings 属性声明的两种替代方案:

  1. 使用反射 API 的“名称”声明属性
  2. 带有反射 API 的“符号”(尤其是 TermSymbol)的属性声明

如果我这样做,据我所知,构建 DTO 的 API 用户将不得不处理反射 API 及其名称/符号。 API 的实现也必须使用反射 API。所以有两个地方有反射代码,用户必须至少对反射 API 有一点了解。

问题

但是我不知道这些方法有多重要:

  • 名称或符号的构建成本高吗?
  • 反射 API 是否对昂贵的操作结果进行任何缓存,还是我应该注意这一点?
  • 名称和符号是否可以通过网络传输到另一个 JVM?
  • 它们可以序列化吗?

主要问题:Scala 反射 API 名称或符号是否足以在传输对象内部使用?

使用反射 API 执行此操作似乎很复杂。欢迎任何提示。以及其他替代方案的任何提示。

P.S.:我还没有包含我自己的代码,因为我的 API 很复杂,并且反射部分处于相当实验状态。我可以稍后提供一些有用的东西。

【问题讨论】:

    标签: scala reflection dto data-transfer-objects


    【解决方案1】:

    1a) 名称易于构造且重量轻,因为它们比字符串多一点。

    1b) 符号不能由用户构造,而是在使用 staticClassmember 等 API 解析名称时在内部创建。对此类 API 的第一次调用通常涉及从 ScalaSignature 注释中解压缩符号所有者的类型签名,因此它们的成本可能很高。后续调用使用已加载的签名,但仍需支付在某种哈希表 (1) 中按名称查找的成本。 declaration 的成本低于 member,因为 declaration 不考虑基类。

    2) 类型签名(例如类成员列表、参数 + 方法的返回类型等)是延迟加载的,因此会被缓存。 Java 和 Scala 反射工件之间的映射也被缓存(2)。据我所知,其余部分(例如子类型检查)通常是未缓存的,但有一些小例外。

    3-4) 反射工件取决于它们的宇宙,目前无法序列化(3)

    【讨论】:

    • 谢谢回答。与普通字符串相比,Names 有什么优势吗?
    • 名称被缓存+名称提供区分术语和类型的标签。更新。我的意思是,即使底层字符串相等,newTermName("C") 也不同于 newTypeName("C")。
    猜你喜欢
    • 2023-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多