0

Suppose I have this two interfaces...

public interface ObjectInterface { /* empty interface */ }

public interface ObjectHandler
{
    void handle(ObjectInterface object);
}

...and also a concrete class which implements the ObjectInterface:

public class ConcreteObject implements ObjectInterface { /* ... */ }

Why is this not allowed in Java?

public class ConcreteHandler implements ObjectHandler
{
    @Override
    public void handle(ConcreteObject object) // <-- ObjectInterface implementation
    {
        // ...
    }
}

A ConcreteObject implements the ObjectInterface interface afterall.
However, is there a way to design my classes in Java keeping this pattern of abstraction?

2
  • 1
    Runtime covariance is not allowed with method parameters - only return types. Commented Jan 26, 2016 at 11:59
  • "Why is this not allowed in Java?" Why should it be allowed? You're actively restricting the passable objects for ConcreteHandler#handle since it only accepts ConcreteObject and not the broader type ObjectInterface. So it fails to correctly implement the ObjectHandler interface. Commented Jan 26, 2016 at 11:59

3 Answers 3

2

You can parameterize ObjectHandler with the class of accepted ObjectInterfaces:

public interface ObjectHandler<T extends ObjectInterface> 
{
    void handle(T object);
}

and use it as follows:

public class ConcreteHandler implements ObjectHandler<ConcreteObject>
{
    @Override
    public void handle(ConcreteObject object) // <-- now this works
    {
        // ...
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Note: Under the hood, the javac compiler generates a method void handle(ObjectInterface oi) { handle((ConcreteObject) oi); } as a synthetic method for you +1
2

Interface method is the contract,

void handle(ObjectInterface object);

Therefore the implementation of the interface should adhere to the contract. So it won't let you limit the object type it accepts.

handle(ConcreteObject object){...}

Above limits the input to the method, as its just a one implementation of ObjectInterface. Think what happens if there's another implementation called, ConcreteObject2 which implements the ObjectInterface. According to your code handle method won't accepts the ConcreteObject2 type objects. If you want to keep the pattern you can use java generics

Comments

2

Because you're breaking the contract of the interface, and thus breaking the Liskov substitutioon principle.

The interface says: handle() can take any instance of ObjectInterface as argument. That's the contract: any implementation of handle() must accept any instance of ObjectInterface.

But the class says: handle() only accepts instances of ConcreteHandler.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.