Question

For a project I want to provide a generic interface to resemble a workflow, like

public interface IWorkflow
{
    public void start();
    public void doWork();
    public void end();
}

For that, I have lots of implementation, like

public class CoffeeWorkflow implements IWorkflow  
{
    public void start() 
    {
        // setup coffee
        // prepare dishes
        // ...
    }

    public void doWork()
    {
         // drink coffee
    }

    public void end()
    { 
         // wash dishes
    }
}

Now I want to provide more information to those functions, like

public interface IWorkflowStartArgs
{}

And especially:

public class CoffeeWorkflowStartArgs implements IWorkflowArgs

To give it into the method

public interface IWorkflow
{
    public void start(IWorkflowStartArgs args);
    public void doWork();
    public void end();
}

respectivly:

public class CoffeeWorkflow implements IWorkflow  
{
    public void start(CoffeeWorkflowStartArgs args) 
    {
    }
}

But this does not work, as it is not recognized as implementation of the interface.

Should I pass in an IWorkflowStartArgs and cast it inside?

Is there a better solution to that?

Was it helpful?

Solution

You can define interface like

interface IWorkflow<T extends IWorkflowStartArgs>
{
    public void start(T args);
    public void doWork();
    public void end();
}

and when you create CoffeeWorkflow you can create something like

class CoffeeWorkflow implements IWorkflow<CoffeeWorkflowStartArgs>
{

    @Override
    public void start(CoffeeWorkflowStartArgs args) {
        // TODO Auto-generated method stub

    }

    @Override
    public void doWork() {
        // TODO Auto-generated method stub

    }

    @Override
    public void end() {
        // TODO Auto-generated method stub

    }
}

OTHER TIPS

Java won't consider it as the specific implementation type. Consider the following case, where you can see where the problem will occur (IF automatic mapping of implemented class in the function argument is seen valid by Java):

public class CoffeeWorkflow implements IWorkflow  
{
    public void start(IWorkflowStartArgs args) 
    {
      // This is what Java sees as actual implementation
    }

    public void start(CoffeeWorkflowStartArgs args) 
    {
       // This is yet again SEPARATE method with different signature
       // In case of auto-casting (if there would have been), this method would be AMBIGUOUS
    }
}

The solution?

Well use Generics as illustrated by @sanbhat

Or if you don't want to go into Generics, Then I think you should pass in an IWorkflowStartArgs and cast it inside as you said first, like this way:

public class CoffeeWorkflow implements IWorkflow  
{
    public void start(IWorkflowStartArgs args) 
    {
        if (args instanceof CoffeeWorkflowStartArgs) {
           CoffeeWorkflowStartArgs coffeeArgs = (CoffeeWorkflowStartArgs) args;
           // ....
        }
    }

    // ....
}

Suppose you have another similar class TeaWorkFlow, then again you need to check instanceof. This is why Generics were mainly introduced - To avoid repeatedly checking by instanceof; And to serve as a general model for similar pattern classes.

There is a solution using a single generic parameter, that ensures type safety. Lets use the generic parameter WorkflowType for it:

interface IWorkflow<T extends WorkflowType>
{
  public void start(IWorkflowStartArgs<T> args);
  public void doWork(IWorkflowWorkArgs<T> args);
  public void end(IWorkflowEndArgs<T> args);
}

You can now instantiate your generic parameter:

public class CoffeeWorkflowType extends WorkflowType {
}

Your CoffeeWorkflow looks like this:

public class Coffee implements IWorkflow<CoffeeWorkflowType> {
{
  public void start(IWorkflowStartArgs<CoffeeWorkflowType> args);
  public void doWork(IWorkflowWorkArgs<CoffeeWorkflowType> args);
  public void end(IWorkflowEndArgs<CoffeeWorkflowType> args);
}

and the implementations for your workflow arguments:

public class CoffeeWorkflowStartArgs implements IWorkflowStartArgs<CoffeeWorkflowType> { ... }
public class CoffeeWorkflowWorkArgs implements IWorkflowWorkArgs<CoffeeWorkflowType> { ... }
public class CoffeeWorkflowEndArgs implements IWorkflowEndArgs<CoffeeWorkflowType> { ... }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top