2016-12-29 3 views
4

У меня есть следующие классы Groovy:Guice, Groovy, @Canonical и наследование не играет хорошо вместе

enum Protocol { 
    File, 
    Ftp, 
    Sftp, 
    Http, 
    Https 
} 

@Canonical 
abstract class Endpoint { 
    String name 
    Protocol protocol 
} 

@Canonical 
@TupleConstructor(includeFields=true, includeSuperFields=true) 
class LocalEndpoint extends Endpoint { 
} 

class MyAppModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     // Lots of stuff... 
    } 

    // Lots of other custom providers 

    @Provides 
    Endpoint providesEndpoint() { 
     new LocalEndpoint('fileystem', Protocol.File) 
    } 
} 

Не беспокоиться о том, почему я использую пользовательский поставщик для Endpoint вместо просто:

bind(Endpoint).toInstance(new LocalEndpoint('fileystem', Protocol.File)) 

Я 99.999% уверен, что это вне этой проблемы и закодировано таким образом из-за того, что полный (очень большой) код подключен.

Моя проблема заключается в том, что Guice и/или Groovy не может найти конструктор для LocalEndpoint, который принимает String и Protocol аргумент:

1) Error in custom provider, groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.example.myapp.model.LocalEndpoint(java.lang.String, com.example.myapp.model.Protocol) 
    at com.example.myapp.inject.MyAppModule.providesEndpoint(MyAppModule.groovy:130) 
    while locating com.example.myapp.model.Endpoint 
    for parameter 2 at com.example.myapp.inject.MyAppModule.providesConfig(MyAppModule.groovy:98) 
    at com.example.myapp.inject.MyAppModule.providesConfig(MyAppModule.groovy:98) 
    while locating com.example.myapp.config.MyAppConfig 

Затем выплевывает большой трассировки стека со следующими перечислены в качестве причины:

Caused by: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.example.myapp.model.LocalEndpoint(java.lang.String, com.example.myapp.model.Protocol) 
     at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1731) 
     at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1534) 

Надеюсь, это то, что я могу настроить путем изменения Endpoint и/или LocalEndpoint, возможно, мне нужно пройти некоторые специальные параметры в @Canonical/@TupleConstructor аннотации или еще что-то. Есть идеи?

+2

Квалифицируйтесь параметры в конструкторе new LocalEndpoint (name: 'fileystem', protocol: Protocol.File) –

+0

Спасибо @ToddWCrone (+1), но мне не нравится конструктор карты Groovy. Благодаря '@ Canonical',' @ TupleConstructor' и тому подобное, я должен использовать обычный вызов конструктора Java-стиля. Любые предложения о том, как получить этот рабочий конструктор sans map? Еще раз спасибо! – smeeb

+0

Квалифицированные имена параметров лучше ИМО. Я бы не потратил много усилий, пытаясь заставить работать более двусмысленный конструктор. Сожалею. –

ответ

3

Я думаю, вам нужно добавить includeSuperProperties в TupleConstructor аннотацию, и это, кажется, решить ее, даже сам по себе:

@TupleConstructor(includeSuperProperties=true)

Так что все это было бы:

@Canonical 
abstract class Endpoint { 
    String name 
    Protocol protocol 
} 

@Canonical // You may not need this anymore 
@TupleConstructor(includeSuperProperties=true) 
class LocalEndpoint extends Endpoint { 
} 
+0

Спасибо @Igor (+1) - **, который сработал !!! ** Один быстрый вопрос о повторении, прежде чем я смогу наградить вас щедростью: раньше у меня был 'includeSuperFields = true'. Почему (в моем конкретном случае) работает 'includeSuperProperties', но * не *' includeSuperFields'? В чем разница между тем, когда +, где использовать каждый из них? Еще раз спасибо!! – smeeb

+0

@smeeb Да, это странное поведение. Я бы ожидал, что что-либо, полученное 'includeSuperProperties', также получит что-либо в' includeSuperFields'. Документация также не слишком подробно описана, поэтому я не уверен. Лучше всего, чтобы посмотреть на реализацию: - \ – Igor

Смежные вопросы