Java Co-Variance

时间:2013-08-13 10:53:54

标签: java interface covariance

对于一个项目,我想提供一个类似工作流的通用界面,比如

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

为此,我有很多实现,比如

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

    public void doWork()
    {
         // drink coffee
    }

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

现在我想为这些功能提供更多信息,比如

public interface IWorkflowStartArgs
{}

特别是:

public class CoffeeWorkflowStartArgs implements IWorkflowArgs

将其纳入方法

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

分别是:

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

但这不起作用,因为它不被认为是实施 的界面。

我应该传入IWorkflowStartArgs并将其投射到内部吗?

有更好的解决方案吗?

3 个答案:

答案 0 :(得分:3)

您可以定义类似

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

当您创建CoffeeWorkflow时,您可以创建类似

的内容
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

    }
}

答案 1 :(得分:2)

Java不会将其视为特定的实现类型。 考虑以下情况,您可以在其中查看问题发生的位置(如果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
    }
}

解决方案?

好好使用@sanbhat

所示的泛型

或者如果你不想进入泛型, 然后我认为你应该传入一个IWorkflowStartArgs并将其放入内部,如你所说的那样, 像这样:

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

    // ....
}

假设您有另一个类似的类TeaWorkFlow, 然后你需要检查instanceof。 这就是为什么主要介绍泛型 - 为避免instanceof重复检查; 并作为类似模式类的通用模型。

答案 2 :(得分:1)

使用单一通用参数的解决方案可确保类型安全。让我们使用通用参数WorkflowType:

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

您现在可以实例化您的通用参数:

public class CoffeeWorkflowType extends WorkflowType {
}

您的CoffeeWorkflow如下所示:

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

以及工作流参数的实现:

public class CoffeeWorkflowStartArgs implements IWorkflowStartArgs<CoffeeWorkflowType> { ... }
public class CoffeeWorkflowWorkArgs implements IWorkflowWorkArgs<CoffeeWorkflowType> { ... }
public class CoffeeWorkflowEndArgs implements IWorkflowEndArgs<CoffeeWorkflowType> { ... }