Мой пример выполнен с помощью Koshuke args4j's@Option
аннотация, но то же самое применимо к любой другой аннотации метода. Чтобы уточнить, эта аннотация может использоваться с любым полем или сеттером.Есть ли способ наследовать аннотацию метода интерфейса в Groovy? (возможный сбой в @Delegate)
Он работает следующим образом:
class AnOptionExample {
@Option(name = '-text')
String text
}
И тест:
def 'recognises option from simple object'() {
given:
def options = new AnOptionExample()
def parser = new CmdLineParser(options)
when:
parser.parseArgument('-text=whatever')
then:
options.text == 'whatever'
}
Теперь предполагая, я хотел бы аннотацию на уровне интерфейса, а затем повторно использовать @Option
определений, а также иметь тип множественного наследования, который позволил бы использовать различные интерфейсы для разных опционных наборов, мы здесь (упрощенный пример):
interface Credentials {
@Option(name = '-username')
void setUsername(String username)
@Option(name = '-password')
void setPassword(String username)
String getUsername()
String getPassword()
}
class CredentialsImpl implements Credentials {
String username
String password
}
Тестовый пример, который показывает отказ:
def 'does not recognise option from interface'() {
given:
def options = new CredentialsImpl()
def parser = new CmdLineParser(options)
when:
parser.parseArgument('-username=John', '-password=qwerty123')
then:
def ex = thrown(CmdLineException)
ex.message == '"-username=John" is not a valid option'
}
Ну, метод аннотации интерфейса не наследуется. Достаточно справедливо - это способ Java, но как насчет Groovy? Некоторые надежды дается следующее:
class SomeOptionsWithDelegate {
@Delegate(methodAnnotations = true)
final Credentials credentials = new CredentialsImpl()
@Option(name = '-url')
String url
}
И тест, который показывает что-то странное:
def 'does recognise option from interface via @Delegate'() {
given:
def options = new SomeOptionsWithDelegate()
def parser = new CmdLineParser(options)
when:
parser.parseArgument('-username=John', '-password=qwerty123', '-url=http://auth.plop.com')
then:
with(options) {
username == 'John'
password == 'qwerty123'
url == 'http://auth.plop.com'
}
}
Удивительно @Delegate(methodAnnotations = true)
работы, несмотря на то, что экземпляр объекта, к которому делегация сделано не имеет аннотаций - только интерфейс Credentials
имеет их. И нет наследования аннотаций метода ... о, подождите, на самом деле в этом суть. Кажется, это сбой. Почему @Delegate
способен воспринимать эти аннотации, указанные на уровне интерфейса, если они не унаследованы CredentialsImpl
?
С другой стороны, я хотел бы иметь точно такое поведение как функции, так что я не должен был бы использовать делегирование здесь, вместо того, чтобы идти, как:
@InheritInterfaceMethodAnnotations
class SomeOptionsViaInterface implements Credentials {
String username
String password
@Option(name = '-url')
String url
}
Очевидно соответствующего теста для приведенного выше примера провалился бы так же, как для второго примера. Таким образом, вопрос: есть ли что-то вроде мнимой аннотации, которую я составил - @InheritInterfaceMethodAnnotations
? Возможна установка с учетом @Delegate
сбой. Как представляется, это полезная функция, возможно, кто-то уже это сделал. Если нет, любой совет, как реализовать его сам по себе, приветствуется.
О, я уверен, что я экспериментировал с чертами, и я был точно такой же результат, как и с интерфейсами. Я еще раз посмотрю, спасибо. – topr