Можно ли напрямую ссылаться на класс конструктора, объявленный с помощью @Builder? - PullRequest
0 голосов
/ 20 сентября 2018

Не удается скомпилировать следующий скрипт Groovy:

import groovy.transform.builder.Builder

@Builder
class Foo {
    String bar
}

Foo.FooBuilder aBuilder = Foo.builder()

Ошибка компиляции:

Ошибка: (8, 16) Groovyc: невозможно разрешить класс Foo.FooBuilder

Это ожидаемое поведение?Любые известные обходные пути?

Groovy версия: 2.5.2 (я тоже проверял 2.4.12 и 2.4.15)

1 Ответ

0 голосов
/ 20 сентября 2018

Это правильно.Строка

Foo.FooBuilder aBuilder = Foo.builder()

потерпит неудачу во время фазы Phases.SEMANTIC_ANALYSIS, которая пытается разрешить все ожидаемые типы (те, которые объявлены слева).Эта фаза выполняется до Phases.CLASS_GENERATION, который генерирует класс FooBuilder - поэтому компилятор жалуется на несуществующий класс FooBuilder (он просто еще не был создан).

Обходной путь

Существует один простой способ решения этой проблемы - используйте def и введите вывод, чтобы пройти фазу семантического анализа и позволить компилятору сгенерировать класс FooBuilder.

import groovy.transform.builder.Builder

@Builder
class Foo {
    String bar
}

def aBuilder = Foo.builder()

println aBuilder.dump()

Так же, как примечание: есть один способ заставить Foo.FooBuilder aBuilder = Foo.builder() пройти этап статического анализа.Если вы пропустите объявление Foo.FooBuilder type

import groovy.transform.builder.Builder

@Builder
class Foo {
    String bar
}

//Foo.FooBuilder aBuilder = Foo.builder()

и скомпилируете этот класс с помощью компилятора groovyc, он сгенерирует Foo.class, а также Foo$FooBuilder.class.Затем, если вы раскомментируете строку, которая вызывает исключение при компиляции, и вы запустите скрипт, он скомпилируется и запустится без каких-либо проблем.Хитрость в том, что Groovy-компилятор компилирует класс Foo.FooBuilder (и сохраняет его как файл Foo$FooBuilder.class), поэтому, когда вы запускаете сценарий и статический анализ пытается его разрешить, он доступен в текущем пути к классам.В этом случае фаза семантического анализа не сообщает об ошибке, с которой вы столкнулись ранее.Однако я упоминаю это только как интересный факт, а не как обходной путь, потому что с ним довольно сложно работать.Вместо этого лучше всего использовать ключевое слово def и полагаться на вывод типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...