WilssoN93
WilssoN93

Reputation: 97

generic interface with parameterized method types

Im trying to make a generic interface since these methods are used in almost all services i have , but when im trying to implement these methods all im getting is a "Method does not override method from its superclass".

@Service
public interface CustomInterface {

    <T, R> List<T> get(final R req);

    <T> T getById(final String id);

    <T, R> T create(final R req);

    <T, R> T update(final String id, final R req);

    <T, R> T patch(final String id, final R req);

    <T> T delete(final String id);

}
///// This is the implementation of one of the methods!
@Override
public CustomerResponseObject create(final CustomObject req) {
    return null;
}

What am i doing wrong? i really thought this would work!

Upvotes: 0

Views: 1026

Answers (2)

Samuel Marchant
Samuel Marchant

Reputation: 330

The methods used in the interface must be "overridden (solid completed code of each interface method signature) inside the class" that implements the origin interface code. An interface definition of method signatures is full of abstract signatures with no body code. A proper class object will have completed usable coded method signatures. When the class is written to implement the interface the polymorphic factor of typing allows the class instance to be referred to as the same as the type of interface rather than the type of the class, however the class instance is both types and too any instance of a variable of its interface type instantiated from the class'es new instance variable.

Upvotes: 0

rzwitserloot
rzwitserloot

Reputation: 103463

You seem to misunderstand generics.

Crucially, they link things. They are figments of the compiler's imagination (the JVM runtime doesn't know what generics are, doesn't apply them, doesn't care about them - and most generics are in fact completely eliminated during compilation, they aren't in the class file at all), so their only purpose is for the compiler to help you out and inform you where you're making potential typing errors.

Thus, they link - they let you say to the compiler: "Hey, this method? It can take some object that is an instance of a class that is Number or a subtype thereover. And then, it returns the same type it was given". It can you let you link the return type to a parameter's type, or link two parameter types together, or they can link the component type of a list that shows up as a field in your class to a parameter of a method elsewhere in the class, etc.

If your generics type shows up in only one place it is useless.

Every single type param you have used in your example is therefore completely useless, and I thus conclude you don't understand the mechanism.

<T, R> T create(final R req); means the following:

For any given invocation of a call to this create method, there is some type we shall decree T and some type we shall refer to as R, solely for this method invocation (vs. generics on a type itself, which are per instance, effectively). They have no bounds (<T extends Number> is known as a 'bound'. Just <T> means it's boundless; any type is fine).

The return type is T and the parameter is R.

Given that there are no bounds, this is just a weird way to write:

Object create(Object req);

And what you implemented isn't that.

<T, R> in this construct declares the type variables; all the other occurrences of them use them. Given that you've declared them for each and every method here, they are all completely unrelated type variables. It's like this:

void foo() {
    int x = 5;
}

void bar() {
    int x = 10;
}

There is zero relationship between these two local vars. They are both named x, which doesn't make them related at all. The same applies to your code: Each method has its own type var that is unique; the fact that they are all named T or R doesn't make them any more related to each other.

Presumably, what you intended to do is for this custominterface that the types are related.

That means it needs to be a property of the type itself:

public interface CustomerInterface<T, R> {
    List<T> get(R req);
    T getById(String id);
    T create(R req);
    // etc
}

Now all those Ts and Rs are in fact referring to the same thing, and now you are linking things. You can then write an implementation which compiles fine:

public class MyCustomImpl implements CustomerInterface<CustomObject, CustomerResponseObject> {
    public CustomerResponseObject create(final CustomObject req) {
      ..
    }
}

and this will compile just fine.

NB: Don't make arguments in interface methods 'final' - it's pointless code clutter.

Upvotes: 2

Related Questions