2017-01-08 1 views
0

Je développe une application Java basée sur JAX-RS en utilisant Google Guice pour l'injection de dépendances. Je l'interface suivante dans mon code:Interface de liaison générique de Guice pour le paramètre de type borné de l'implémentation

public interface LockProvider<L extends Lock> { 
    Optional<L> acquireLock(String lockId); 

    void releaseLock(L lock); 
} 

Dans l'interface ci-dessus, verrouillage est une interface définie comme suit:

public interface Lock { 
    String getLockId(); 
} 

Interface Lock est mis en œuvre par la classe suivante:

public class DynamoDBLock implements Lock { 
    private final String lockId; 
    private final LockItem underLyingLock; 

    public DynamoDBLock(final String lockId, final LockItem underLyingLock) { 
    this.lockId = lockId; 
    this.underLyingLock = underLyingLock; 
    } 

    @Override 
    public String getLockId() { 
     return lockId; 
    } 

    public LockItem getUnderlyingLock() { 
     return underlyingLock; 
    } 
} 

L'interface LockProvider est implémentée par la classe suivante:

public class DynamoDBLockProvider implements LockProvider<DynamoDBLock> { 
    Optional<DynamoDBLock> acquireLock(String lockId) { 
     //implementation here 
    } 

    void releaseLock(DynamoDBLock lock) { 
     LockItem underlyingLockItem = lock.getUnderlyingLockItem(); 
     //do something with underlyingLockItem 
    } 
} 

Je ne souhaite pas que les classes de mon application, autres que LockProvider, connaissent l'élément de verrouillage sous-jacent, c'est pourquoi je n'ai pas inclus getUnderlyingLockItem dans l'interface de verrouillage.

Maintenant, lorsque je tente de lier LockProvider à DynamoDBLockProvider comme suit:

bind(new TypeLiteral<LockProvider<Lock>>() {}).to(DynamoDBLockProvider.class); 

Je reçois l'erreur de compilation suivante dans Eclipse:

 
The method to(Class<? extends LockProvider<Lock>>) in the type LinkedBindingBuilder<LockProvider<Lock>> is not applicable for the arguments (Class<DynamoDBLockProvider>) 

Je comprends que DynamoDBLockProvider <DynamoDBLock> est pas une sous-classe de LockProvider <Lock>. Est-il possible d'accomplir ce que j'essaie de faire, c'est-à-dire de lier LockProvider à DynamoDBLockProvider (d'une manière propre et efficace)?

+1

La solution a fonctionné pour moi. J'ai édité pour l'exhaustivité; J'avais oublié d'échapper moins et plus que des signes. –

Répondre

1

vos instances de DynamoDBLockProvider sont pas cas de LockProvider<Lock>. Mais ils sont instances de LockProvider<? extends Lock>.

Un exemple parallèle serait de cas ArrayList<Integer> sont pas cas de List<Number> mais sont des instances de List<? extends Number> comme par this question.

Appliquez cela à Guice et vous obtiendrez exactement la même erreur de compilation. Supposons que vous avez une classe comme ceci:

public class IntegerList extends ArrayList<Integer> {} 

comme liant alors cela ne fonctionnera pas:

binder.bind(new TypeLiteral<List<Number>>() {}).to(IntegerList.class); //won't compile 

Est-il possible d'accomplir ce que je suis en train de faire, par exemple LockProvider de se lier à DynamoDBLockProvider (d'une manière propre et efficace)?

La liaison suivante fonctionnera:

binder.bind(new TypeLiteral<LockProvider<? extends Lock>>() {}).to(DynamoDBLockProvider.class);