Реализация универсального интерфейса в Groovy - PullRequest
0 голосов
/ 01 марта 2019

Редактировать: . Урезать до основной проблемы.

Я пытаюсь реализовать Springs CrudRepository<T, ID> в классе Groovy, который не может быть скомпилирован с:

Не может иметь абстрактный метод в неабстрактном классе.Класс [..] должен быть объявлен как абстрактный или должен быть реализован метод ' java.lang.Object save (java.lang.Object) '.

Эти ошибки влияют наметоды только с подписью <S extends T>.Для проблем с Generics имеется ошибка Groovy, но она должна быть решена!Я сохранил ответ на этот вопрос и добавил модификаторы, но все еще не могу скомпилировать.

Пример

Следующий код не будет компилироваться в консоли IntelliJ Groovy на моем компьютеремашина, использующая javac, Eclipse-компилятор или Groovy-Eclipse.

class Account { int id }

interface Repo<T, ID> {
    public T get(ID id)
    public <S extends T> S save(S entity)
}

class AccountRepo implements Repo<Account, Long> {

    @Override
    Account get(Long aLong) {
        return null
    }

    @Override
    public <S extends Account> S save(S entity) {
        return null
    }
}
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
ideaGroovyConsole.groovy: 9: Can't have an abstract method in a non-abstract class. The class 'AccountRepo' must be declared abstract or the method 'java.lang.Object save(java.lang.Object)' must be implemented.
 @ line 9, column 1.
   class AccountRepo implements Repo<Account, Long> {
   ^

1 error

Просто для записи, я использую Groovy 2.5.4.

1 Ответ

0 голосов
/ 05 апреля 2019

Единственный способ найти это - написать класс адаптера Java, который связывает методы с Generics в их сигнатуре:

public abstract class RepositoryGenericsAdapter<T extends Identifiable, ID> implements CrudRepository<T, ID> {

    @Override
    public <S extends T> S save(S entity) {
        // getId() provided via Identifiable interface
        if (entity.getId() == null) {
            create(entity);
        } else {
            update(entity);
        }

        return entity;
    }

    @Override
    public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
        entities.forEach(this::save);
        return entities;
    }

    // These operations accept generic class type <T> instead of <S extends T>:

    protected abstract void update(T entity);

    protected abstract void create(T entity);
}

Пока интерфейс остается неизменным, реализация Groovy расширяетсяАдаптер и реализует абстрактные методы:

class AccountRepo extends RepositoryGenericsAdapter<Account, Long>
        implements Repo<Account, Long> {

    @Override
    Account get(Long aLong) {
        // ...
    }

    @Override
    public Account create(Account entity) {
        // ...
    }

    @Override
    public Account update(Account entity) {
        // ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...