2017-01-08 5 views
0

Я разрабатываю Java-приложение на основе JAX-RS, используя Google Guice для инъекции зависимостей. У меня есть следующий интерфейс в моем коде:Общий интерфейс связывания Guice с параметром ограниченного типа реализации

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

    void releaseLock(L lock); 
} 

В приведенном выше интерфейс, блокировка представляет собой интерфейс, определяется следующим образом:

public interface Lock { 
    String getLockId(); 
} 

интерфейс Блокировка осуществляется с помощью следующего класса:

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; 
    } 
} 

Интерфейс LockProvider реализуется следующим классом:

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 
    } 
} 

Я не хочу, чтобы классы в моем приложении, кроме LockProvider, знали о элементе блокировки underLing, поэтому я не включил getUnderlyingLockItem в интерфейс Lock.

Теперь, когда я пытаюсь связать LockProvider с DynamoDBLockProvider следующим образом:

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

Я получаю следующее сообщение об ошибке компиляции в Eclipse:

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

Я понимаю, что DynamoDBLockProvider <DynamoDBLock> не подкласс LockProvider <Lock>. Можно ли выполнить то, что я пытаюсь сделать, т. Е. Привязать LockProvider к DynamoDBLockProvider (чистым и эффективным способом)?

+1

решение работает для меня. Я редактировал для полноты; Я забыл бежать меньше и больше, чем знаки. –

ответ

1

Ваши экземпляры DynamoDBLockProvider являются не экземпляры LockProvider<Lock>. Но они являются экземпляров LockProvider<? extends Lock>.

Параллельный Пример может быть экземпляры ArrayList<Integer> являются не экземпляров List<Number> но являются экземпляров List<? extends Number> как за this question.

Примените это к Guice, и вы получите точно такую ​​же компиляцию. Предположим, у вас есть класс вроде этого:

public class IntegerList extends ArrayList<Integer> {} 

Затем его связывания, как это не будет работать:

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

Можно ли сделать то, что я пытаюсь сделать, то есть привязки LockProvider к DynamoDBLockProvider (чистым и эффективным способом)?

Следующая связывание будет работать:

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