pr0gma
pr0gma

Reputation: 575

How to use an interface as a parameter for another interface's function?

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?

Upvotes: 0

Views: 107

Answers (3)

JB Nizet
JB Nizet

Reputation: 691635

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.

Upvotes: 2

Isuru Gunawardana
Isuru Gunawardana

Reputation: 2887

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

Upvotes: 2

wero
wero

Reputation: 32980

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
    {
        // ...
    }
}

Upvotes: 2

Related Questions