Инициализация фабрики во время компиляции
У меня есть фабрика, которая должна возвращать реализацию в зависимости от имени.
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
с моей точки зрения может быть только генерация кода из макросов или на основе скаламеты.