1

我有一个工厂,它应该根据名称返回一个实现。

    val moduleMap = Map(Modules.moduleName -> new ModuleImpl)
    def getModule(moduleName: String): Module =
        moduleMap.get(moduleName) match {
          case Some(m) => m
          case _ =>
            throw new ModuleNotFoundException(
              s"$moduleName - Module could not be found.")
        }

为了使对“getModule”方法的每次调用不创建实例,有一个映射,其中所有模块都必须在引导类中初始化。我想摆脱手动执行此操作的需要(所有类都有一个独特的功能)。

我想到的选项列表:

  • 反射(我们可以使用 Scala 反射 API 或任何第三方库)
    • 自动化过程。
    • 需要在启动时立即初始化。
    • 反思是一种痛苦。
  • 元编程(ScalaMeta)+反射
    • 宏只更改代码,稍后执行。

我们可以将初始化过程移到编译时间吗?

我知道编译器可以优化和替换代码,编译前的下一个片段

val a = 5 + 5

在编译编译器将该部分更改为 10 之后,我们可以使用一些指令或其他工具在编译时评估和执行一些代码并仅使用最终值吗?

4

1 回答 1

0

您使用任何框架还是编写自己的框架?我在这里回答了关于 Guice 的类似问题。你也可以在没有 Guice 的情况下使用它:Module你将拥有你的工厂,你需要从某个地方初始化它,并且在初始化期间,你将使用反射填充你的地图

一般来说,我认为这是最简单的方法。或者,您可以编写宏,它只是替换反射初始化的一部分,但不确定它是否会给您带来一些好处(如果我理解您的问题,这个初始化只会在启动时发生一次)。

我不明白 scalameta 可以如何帮助你?可能,只有在您的所有实现都在您可用的源代码树中的情况下,您才能分析它并生成初始化(类似于宏)?可能,这会增加诸如更容易搜索实现的加号,但会增加减号:仅适用于您的源代码中的实现。

您的编译时优化示例不适用。在您的示例中,您讨论了编译时常量(即使使用算术也可能是一个问题,请参阅评论),但在您的问题中,您需要特定的运行时行为。因此compile time,从我的角度来看,只能从宏或基于 scalameta 生成代码。

于 2018-03-26T16:47:32.430 回答