Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

declare parameter subtype in Java interface, use subtypes in Java implementing methods

I want to declare a method in an interface where the parameter of the method defined in implementing classes can be a subtype of a specific java class for example:

interface Processor{
      processRequest( Request r);
}

public class SpecialRequest extends Request{...}

public class SpecialProcessor implements Processor{

      processRequest(SpecialRequest r){...}
}

but I get errors in the SpecialProcessor because it doesn't properly implement the Processor interface. What can I change in the Processor interface to allow the definition in the SpecialProcessor to work?

like image 975
user592672 Avatar asked Jan 27 '11 18:01

user592672


People also ask

What is subtype in Java with example?

In Java, Sis a subtype of T if S extends or implements T. Subtyping is transitive, meaning that if R is a subtype of S, then R is also a subtype of T (T is the super type of both Sand R). Here are some examples: - Integer is a subtype of Number. - ArrayList<E> is a subtype of Collection<E>

Are all Java subclasses subtypes?

Subclass is not the same as subtype. You might create subclasses that are not subtypes.

What does subtype mean in Java?

You can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.

Is integer [] a subtype of Number []?

Although Integer is a subtype of Number, List<Integer> is not a subtype of List<Number> and, in fact, these two types are not related.


2 Answers

You can type Processor:

public interface Processor<R extends Request> {
    void processRequest(R r);
}


public class SpecialProcessor implements Processor<SpecialRequest> {
    public void processRequest(SpecialRequest r) {
       ...
    }
}
like image 160
Mark Peters Avatar answered Sep 23 '22 13:09

Mark Peters


That's right - remember that a caller shouldn't know what specific implementation of the interface is being used. They just know that they can pass a Request (any Request) to processRequest, whereas your implementation is imposing a stricter constraint on the argument that would cause certain method calls not to be type-correct.

If you want to do this, you'll need to add a generic parameter to the interface, something like the following:

interface Processor<R extends Request> {
    void processRequest(R r);
}

public class SpecialProcessor implements Processor<SpecialRequest> {

    public void processRequest(SpecialRequest r) { ... }

}

This way, callers that want to pass in "normal" requests will have to declare a variable/field of type Processor<Request> - and your SpecialProcessor no longer matches this bound, so cannot be assigned, and will correctly be rejected at compile-time. Callers that are dealing with special requests themselves can use a Processor<SpecialRequest> variable/field, which your class can be assigned to.

like image 34
Andrzej Doyle Avatar answered Sep 22 '22 13:09

Andrzej Doyle