quaylar
quaylar

Reputation: 2635

OOP-Design: Interface-Methods with implementation-dependent parameters

The subject says it already:

I am thinking right now about following design-problem: I define an interface for a specific type of object that contains various methods. Now i have the problem, that different implementations of this interface, need additional/different method-parameters (because the way they are implemented makes this necessary), which i cannot incorporate into the interface because they are not common to all interface-implementations.

Now i realize that interface implementations could come with their own property-files, loading their additional parameters from there, but what if these parameters need to be passed in at runtime?

Currently i can only think of passing in a Map<String, Object> parameters to overcome this problem - since JDK-Classes like DocumentBuilderFactory are doing something very similar by providing methods like setAttribute(String attName, Object attValue) this seems like a feasible approach to solve this problem. Nevertheless i would be interested in how others solve issues like this, alternative ideas?

I dont want to derive from the interface and add additional methods, since in my case i would then have to throw NotImplementException from the methods of the base interface.

UPDATE:

What could be eventual problems of the Map-approach? Implementing classes are free to ignore it completely if they cant make use of additional parameters. Others might check if the Map contains the desired parameter-names, check the type of their values and use them if valid, throw an exception if not. I have also seen this being used for the abstract class JAXBContext, so it seems to be a common approach..

UPDATE:

I decided to go for the map-approach, since i dont see any obvious disadvantages and it is being used in the JDK as well (yes, i know this does not necessarily mean much :) Since i cannot accept an answer on this question, i will just upvote. Thanks for your input!

regards,

--qu

Upvotes: 5

Views: 2653

Answers (6)

vulkanino
vulkanino

Reputation: 9124

couldn't you design subinterfaces that extend your (super)interface? anyhow I see a design problem if you need a method with different parameters depending on the implementation!

edit: code to clarify

interface CommonBehaviour
{
    void methodA(int aParam);
}

interface SpecificBehaviour extends CommonBehaviour
{
    void methodB(int aParam, int anotherParam);
}

class SpecificBehaviourImpl implements SpecificBehaviour 
{
   void methodA(int aParam)
   {
      //do something common
   }

   void methodB(int aParam, int anotherParam)
   {
      //do something specific
   }
}

CommonBehaviour myObj = new SpecificBehaviourImpl();

EDIT: You may benefit from the Command pattern: "Using command objects makes it easier to construct general components that need to delegate, sequence or execute method calls at a time of their choosing without the need to know the owner of the method or the method parameters." (source: wikipedia)

I don't think the Map approach to be any good, I may accept it as a fix of existing code that would allow you to have any parameter number and type, but without formal checks! You're trying to define a common behavior (interface methods) given a variable, runtime, state.

Upvotes: 1

yair
yair

Reputation: 9245

You should just initialize each inheritor with its own specific required parameters and let the interface method remain parameter-less, as in:

Interface Runnable:

public interface Runnable {
    public abstract void run();
}

Implementation:

public class MyRunnable {

    private final String myConcreteString;

    public MyRunnable(String myConcreteString) {
        this.myConcreteString = myConcreteString;
    }

    public void run() {
        // do something with myConcreteString
    }
}

Upvotes: 2

Sanctus2099
Sanctus2099

Reputation: 1723

The point of the interfaces is to have something that is common to all implementations. By trying to do this you destroy the whole reason why interfaces exists.

If you absolutely must do that there is a simple enough way that I have used before.

My answer is in C++ because I'm just not that fluent in other languages. I'm sure there are ways to implement this in java as well.

SomeMethod(void* parameterData);

void* parameterData is a pointer to a struct containing your data. In each implementation you know what you are receiving. You can even have a enum to tell you what kind of data you are receiving.

SSomeData* data = (SSomeData)parameterData

EDIT:

Another approach would be to create a new interface for the parameters: IParameterData.
Inside that interface you have 2 methods: GetParameter(name) and SetParameter(name).
For each implementation of your primary interface you create a implementation of IParameterData.

I hope it helps

Upvotes: 1

sje397
sje397

Reputation: 41812

Can you invert the problem, and implement an interface on the user of these objects which they can query for the additional parameters?

So, when you instantiate these objects implementing the common interface, you also pass in (e.g. to their constructor) an object which provides a way of accessing the additional parameters they might require.

Say your interface has a method 'doSomething' taking parameter 'a', but you have an implementation that needs to know what 'b' is inside this 'doSomething' method. It would call 'getB' on the object you provided to it's constructor to get this information.

Upvotes: 0

Kris
Kris

Reputation: 5792

In your place, I would consider finding appropriate design pattern to your problem, rather then try to bend the interface methods to suit your needs. Look into Strategy Pattern for starters.

Upvotes: 0

Rostislav Matl
Rostislav Matl

Reputation: 4543

You should introduce parameter object representing a super-set of possible arguments.

Upvotes: 0

Related Questions