Why I can not override method using implementation of class as parameter

hudi :

I have simple abstract structure

public abstract class Data<A extends Serializable> {

}

and then String implementation of this class

public class StringData extends Data<String> {

}

then I have Interface:

public interface Testicek<A extends Serializable> {

    public abstract Data<A> test(Data<A> bla);

}

and now I want to create class which implement this interface:

public class TesticekImpl implements Testicek<String> {


    // OK
    @Override
    public StringData test(Data<String> bla) {
        return null;
    }

    // compilation error
    //@Override
    //public StringData test(StringData bla) {
    //    return null;
    //}

}

Why I can not use my StringData class as parameter and it only works in return type ? Signatures of return type and parameter are same.

Andy Turner :
public interface Testicek<A extends Serializable> {

    public abstract Data<A> test(Data<A> bla);

}

Java allows covariant return types, which means that implementations of an interface can return more specific types than the parent interface, because those more-specific types are still instances of less-specific types, and thus they meet the contract of the interface.

However, you can't use more specific parameter types, because the contract of the interface says that it must accept any instance of that type.

The Liskov Substitution Principle tells us that subclasses have to accept parameters that are no more restrictive, and must return values that are no more general.

Java doesn't allow you to use "less restrictive" parameter types, because of the way it resolves methods to invoke at compile time (which is already pretty complicated). This is unnecessarily restrictive from a theoretical point of view, but simpler from a practical point of view.

In terms of you accepting and returning the same type: declare another type variable in your interface:

public interface Testicek<A extends Serializable, D extends Data<A>> {

    public abstract D test(D bla);

}

Then your implementation can be:

public class TesticekImpl implements Testicek<String, StringData> {
    @Override
    public StringData test(StringData bla) {
        return null;
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=75543&siteId=1