简体   繁体   中英

java method generics implementing interface

What is wrong with this code?

public interface FileProccessor {
    public <RT> RT setHeader(RT header);
}

public class AProcessor implements FileProccessor {

    @Override
    public Header setHeader(Header header) {
        return null;
    }
}

Compilator is complaining: The method setHeader(Header) of type AProcessor must override or implement a supertype method

Edit: Thanks. I got confused because I wanted multiple methods with different types. Now I realized a can add as many parametrized types as I want in class level. Like FileProcessor<T, F, M> .

Your interface declaration specifies that all implementations of the interface will provide a generic method with this signature:

public <RT> RT setHeader(RT header);

In other words, the caller would be able to pass an object of any type, and get back an object of the same exact type.

You implementation declaration, on the other hand, limits the user to a single type, ie the Header . That's why the compiler is complaining about inability to override.

The trick would work if the interface were generic, and a type implementing it was implementing a generic instance, like this:

public interface FileProccessor<T> {
    public T setHeader(T header);
}

public class AProcessor implements FileProccessor<Header> {
}

I think you wanna do this:

public interface FileProccessor<RT, RX> {
    public RT setHeader(RT header);
    public RX setFooter(RX footer);
}

public class AProcessor implements FileProccessor<Header, Footer> {

    @Override
    public Header setHeader(Header header) {
        return null;
    }

    @Override
    public Footer setFooter(Footer footer) {
        return null;
    }
}

Try defining your interface like this:

public interface FileProccessor<RT> {
    public RT setHeader(RT header);
}

And then implement it like this:

public class AProcessor implements FileProccessor<Header> {
    @Override
    public Header setHeader(Header header) {
        return null;
    }
}

You cannot override a method this way. AProcessor must be able to accept everything that FileProcessor accepts as input to setHeader . Consider this code:

FileProcessor f = new AProcessor();
String s =  f.setHeader("Bah");

This code should work no matter which concrete class is used, and it doesn't with your AProcessor . Therefore it makes sense that the type checker rejects it.

Something like this would work (since the FileProcessor interface is now parameterized with RT):

public interface FileProccessor<RT> {
    public RT setHeader(RT header);
}

public class AProcessor implements FileProccessor<Header> {

    @Override
    public Header setHeader(Header header) {
        return null;
    }
}

Now the user of the class would have to write:

FileProcessor<Header> f = new AProcessor();

and the argument to setHeader must be of type Header ...

JLS # 8.4.2. Method Signature

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

  • m2 has the same signature as m1, or

  • the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

In your case as erasure is different ie. in once case you have and and in the implementing class you don't have.

Because raw types are allowed to override generic method below can work in your case.

    @Override
    public Object setHeader(Object header) {
        return null;
    }

Also if you change your declaration like below

 public interface FileProccessor<T> {
    public T setHeader(T header);
 }

You can override method based on Type passed in FileProccessor<T> in the child class while extending

public class AProcessor implements FileProccessor<Header> {
    @Override
    public Header setHeader(Header header) {
        return null;
    }
}

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