Общий интерфейс и реализация - тип не может быть преобразован - PullRequest
3 голосов
/ 30 мая 2019

У меня есть общий интерфейс, определенный как:

public interface ItemService<T extends Slicer, E extends ItemSlice> {
    E getItemHistory(final String id, final T slicer);
}

И реализация:

public class DynamoDbItemService implements ItemService<DynamoDbSlicer, DynamoDbItemSlice> {
    public DynamoDbItemSlice getItemHistory(final String id, final DynamoDbSlicer slicer) {
    }
}

Вот определения четырех упомянутых выше классов:

public interface Slicer {
    Map<String, ? extends Serializable> pointer();
}

public class DynamoDbSlicer implements Slicer {
    public Map<String, AttributeValue> pointer() {
    }
}

public interface ItemSlice extends Slice<Item> {
}

public interface Slice<T> {
    List<T> data();
    Slicer next();
}

public class DynamoDbItemSlice implements ItemSlice {
    publi ImmutableList<Item> data() {}
    public DynamoDbSlicer next() {}
}

Я хотел бы сослаться на интерфейс ItemService, но чтобы он был привязан к реализации DynamoDbItemService, чтобы я мог при необходимости поменять его местами, что я могу сделать так:

ItemService<? extends Slicer, ? extends ItemSlice> itemService = new DynamoDbItemService itemService();

но если я попытаюсь использовать itemService так:

ItemSlice slice = itemService.getItemHistory(itemId, DynamoDbSlicer.first(1));
slice = itemService.getItemHistory(itemId, slice.next());

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

Error:(231, 82) java: incompatible types: item.pagination.DynamoDbSlicer cannot be converted to capture#1 of ? extends pagination.Slicer

Error:(238, 62) java: incompatible types: pagination.Slicer cannot be converted to capture#2 of ? extends pagination.Slicer

Я понимаю из этого вопроса , что ? символы подстановки не могут быть идентичными, поэтому мой вопрос - могу ли я делать то, что я хочу - работать с интерфейсом? Если так, то как? Или я к этому неправильно подхожу?

Я задал два предыдущих вопроса, связанных с этим, которые помогли на этом пути ( первый и второй )

1 Ответ

1 голос
/ 30 мая 2019

Я не вижу причины, по которой следующее не будет работать для вас:

ItemService<DynamoDbSlicer, DynamoDbItemSlice> itemService = new DynamoDbItemService();
ItemSlice slice = itemService.getItemHistory("",  new DynamoDbSlicer());

Но если вы хотите сделать код как можно более модульным, вы можете использовать этот метод для выполненияснимите флажок (некоторые говорят, что это чистое зло) и получите желаемый результат:

public static void main(String[] args) {

    ItemSlice slice = getMySlice(new DynamoDbItemService());
}

@SuppressWarnings("unchecked")
public static <T extends Slicer, E extends ItemSlice> E getMySlice(ItemService<T, E> service) {
    return service.getItemHistory("", (T) new DynamoDbSlicer());
}

И, конечно, есть решение передать ответственность за вывод типа на действительное поле, котороехранение стоимости.Я сам пошел бы на это решение, так как думаю, что оно предлагает наибольшую гибкость:

public class DynamoDbItemService<T extends Slicer, E extends ItemSlice> implements ItemService<T, E>

ItemService<DynamoDbSlicer, DynamoDbItemSlice> itemService = new DynamoDbItemService();
ItemSlice slice = itemService.getItemHistory("", new DynamoDbSlicer());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...