简体   繁体   中英

Implementing Abstract Generic Method in Java with multiple generics types

It is about generics methods in java with two generics types (one for return type and another for a formal parameter) and how to implement it. I guess i am missing something in the picture to get it work.

The matter is this...

This is working :

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

This is not working :

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

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

The java compiler yells me this :

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

Well, that's the situation. Thanks in advance to all!. Hope it helps others in the future!.

PD: It's not a problem of enums types.. it happens across classes hierarchies. So don't bother blaming the enums, i tried this and doesn't work.

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

UPDATED:

For Generics parameters

We can make a general rule statement that for "generics parameter" (those whose types is generic) the type implicitly taken in the method signature is equals to upper limits of that generic, that can be Object, if nothing is specified, or a more specific subclass if upper bounds are used (in example T extends String).

For Generics returns types

There is no problem overwriting a generic method with a specific return type, as long the return type is a subtype of the overwritten return type. And what is the return type at first place? Well, it happens to be Object. By default the compiler assumes (in the method signature) the generic type as an Object type.

So we have to thing that the trick is to know that any method that have a generic return type are actually having an Object return type. Then if in any subclasses the method is overwritten and we alter he return type stating that return another type, there will be no problem. Because, besides that method will return an object of another class, that object returned will inevitable be subclass of the Object class and there will be no problem overwrite a method with a different return type that the original as long it be a subtype of the original. The technique called covariant return type allow us to do such thing.

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


public class SubClass extends SuperClass
{

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

meanwhile in another part of the code...

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

Thanks to all the folks who help clear this out!.

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

is a method that can take anything as argument, and is allowed to return anything.

Overriding it with

public Integer get (DesiredClass entity)

doesn't work, since you restrict the types of argument that can be passed to the method to DesiredClass, and thus break the Liskov principle.

It would be easier to understand without generics. Suppose you have an abstract method in class Bar:

public abstract void fillRecipient(Recipient r);

and you try to override in SubBar it with

public void fillRecipient(Glass glass) {
}

What would the following code do if the above was legal?

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

For completion to JB Nizet's answer , when you write:

<K>

It implicitly means:

<K extends Object>

That method must accept any object. Limiting it to DesiredClass on a subclass effectively overwrites nothing, like the error message says.

overridden methods must have the exact same signature, no sub/super types allowed neither in parameters or return types.

Edit: Actually as discussed in the comments, String public foo(); effectively overrides Object public foo(); .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM