Реализация абстрактного универсального метода в Java с несколькими типами дженериков

Я задам очень короткий вопрос и надеюсь, что кто-то может помочь мне в решении. Он рассказывает о методах дженериков в java с двумя типами дженериков (один для возвращаемого типа и другой для формального пареметра) и о том, как его реализовать. Наверное, я что-то упускаю, чтобы заставить его работать.

дело вот в чем...

это работающего :

public enum Getter
{
    BillItemsSize {
        @Override
        public Integer get (Object entity) {
            DesiredClass ref = (DesiredClass ) entity; // "Old time" cast
            // do things...
        }
    };

    public abstract <T,K> T get (K entity);        
}

это не работает :

public enum Getter
{
    BillItemsSize {
        @Override
        public Integer get (DesiredClass entity) { // no cast at all
            // do things
        }
    };

    public abstract <T,K> T get (K entity);        
}

в Java компилятор кричит мне :

<anonymous datasource.db.Getter> is not abstract and does not override abstract method <T,K>get(K) in Getter

Ну, это ситуация. Заранее спасибо всем!. Надеюсь, это поможет другим в будущем!.

P. D: это не проблема типов перечислений.. это происходит между иерархиями классов. Так что не стоит винить эмунов... я пробовал это и тоже не работает.

public abstract class SuperClass
{
    public abstract <T,E> T pepe (E e);
}

public class SubClass extends SuperClass
{

    @Override
    public Integer pepe(DesiredClass e) // fails... 
    {
        return null;
    }

}

обновление:

для обобщения параметров

мы можем сделать общее правило, что для " дженериков параметр " (те, чьи типы являются универсальными) тип, неявно принятый в сигнатуре метода, равен верхним границам этого универсального, который может быть объектом, если ничего не указано, или более конкретным подклассом, если используются верхние границы (в Примере t расширяет строку).

для дженериков возвращает типы

нет проблем с перезаписью универсального метода с определенным типом возврата, если тип возврата является подтипом перезаписанного типа возврата. И что тип возврата на первом месте? Так случилось, что это объект. По умолчанию компилятор принимает (в сигнатуре метода) универсальный тип в качестве типа объекта.

поэтому мы должны знать, что трюк состоит в том, чтобы знать, что любой метод, имеющий общий тип возврата, на самом деле имеет объект тип возвращаемого значения. Тогда, если в любом подклассе метод перезаписывается и мы изменяем тип возврата, заявляя, что возвращаем другой тип, проблем не будет. Потому что, кроме того, что метод вернет объект другого класса, этот возвращаемый объект неизбежно будет подклассом класса Object, и не будет никаких проблем с перезаписью метода с другим типом возврата, который является исходным, пока он является подтипом оригинала. Метод, называемый ковариантным типом возврата, позволяет нам делать такие вещи.

public abstract class SuperClass
{
    public abstract <T> T operation ();
}


public class SubClass extends SuperClass
{

    @Override
    public Chair operation()
    {
        //bla bla 
    }

}   

тем временем в другой части кода...

void main ()
{
        SubClass sb = new SubClass();
        Chair chair = sb.operation ();
        // the chair type can be easely replaced by super type (like Object)
        Object object = sb.operation();
}

спасибо всем людям, которые помогают убрать это!.

2 ответов


public abstract <T,K> T get (K entity);        

- это метод, который может принимать что угодно в качестве аргумента и может возвращать что угодно.

перекрывая его с

public Integer get (DesiredClass entity)

не работает, так как вы ограничиваете типы аргументов, которые могут быть переданы методу в DesiredClass, и, таким образом, нарушаете принцип Лискова.

было бы легче понять без дженериков. Предположим, у вас есть абстрактный метод в классе-бар:

public abstract void fillRecipient(Recipient r);

и вы пытаетесь переопределить в SubBar это с

public void fillRecipient(Glass glass) {
}

что бы сделал следующий код, если бы вышеуказанное было законным?

Bar bar = new SubBar();
bar.fillRecipient(new Mug());

завершить к JB Nizet это ответ, когда вы пишете:

<K>

это неявно означает:

<K extends Object>

этот метод должен принимать какого-либо объекта. Ограничивая его DesiredClass в подклассе эффективно ничего не перезаписывает, как говорится в сообщении об ошибке.

переопределенные методы должны иметь точно такую же сигнатуру, никакие sub / super типы не разрешены ни в параметрах, ни в возврате типы.

Edit: на самом деле, как обсуждалось в комментариях,String public foo(); эффективно переопределяет Object public foo();.