Инициализация фабрики во время компиляции

У меня есть фабрика, которая должна возвращать реализацию в зависимости от имени.

    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" не создавать экземпляр, существует карта, в которой все модули должны быть инициализированы в классе начальной загрузки. Я хотел бы избавиться от необходимости делать это вручную (также у всех классов есть отличительная особенность).

Список вариантов, которые пришли мне в голову:

  • Reflection (мы можем использовать Scala Reflection API или любую стороннюю библиотеку)
    • Автоматизированный процесс.
    • Нужно инициализировать сразу при запуске.
    • Отражение - это боль.
  • Метапрограммирование (ScalaMeta) + Отражение
    • Макросы только изменяют код, выполнение происходит позже.

Можем ли мы перенести процесс инициализации на время компиляции?

Я знаю, что компилятор может оптимизировать и заменить код, следующий фрагмент перед компиляцией

val a = 5 + 5

после того, как компилятор изменит этот кусок на 10, можем ли мы использовать некоторые директивы или другие инструменты для оценки и выполнения некоторого кода во время компиляции и использовать только окончательное значение?

1 ответ

Используете ли вы какие-либо рамки или вы пишете свои собственные? Я ответил на аналогичный вопрос о Guice здесь. Вы также можете использовать его без Guice: вместо Module у вас будет фабрика, которую нужно откуда-то инициализировать, и во время инициализации вы будете заполнять свою карту с помощью отражения

В общем, я думаю, что это самый простой подход. Кроме того, вы можете написать макрос, который просто заменяет часть отражающей инициализации, но не уверен, что это даст вам некоторую прибыль (если я правильно понимаю ваш вопрос, эта инициализация произойдет только один раз при запуске).

Я не вижу, как скальета может вам помочь? Возможно, только в том случае, если все ваши реализации находятся в исходном дереве, доступном вам, чтобы вы могли проанализировать его и сгенерировать инициализацию (аналогично макросам)? Вероятно, это добавило бы такой плюс как более легкий поиск реализации, но добавит минус: будет работать только на реализациях в ваших источниках.

Ваш пример оптимизации во время компиляции не применим. В вашем примере вы говорите о константе времени компиляции (даже с арифметикой это может быть проблемой, см. Этот комментарий), но в вашем вопросе вам нужно определенное поведение во время выполнения. Так compile time с моей точки зрения может быть только генерация кода из макросов или на основе скаламеты.

Другие вопросы по тегам