如何在Java中处理Scala类型中的Covariancy

时间:2015-11-16 12:27:53

标签: java scala covariance

在我们的Scala项目中,我们使用包含协变类型参数的类型来传达决策。

sealed trait ArbiterResponse[+Tasks]

object Reject extends ArbiterResponse[Nothing]

trait Proceed[Tasks] extends ArbiterResponse[Tasks]
object Proceed extends Proceed[Nothing]
case class ProceedConditionally[Tasks](tasks : Tasks) extends Proceed[Tasks]

从Java中使用时,我收到错误消息,ArbiterResponse<SomeTask>无法转换为Reject$

final ArbiterResponse<SomeTask> response = ???
if (task instanceof Reject$) { ... }
  

错误:不兼容的类型:ArbiterResponse无法转换为Reject $

如何解决此问题?我想这是因为Java编译器不知道共同/逆变。我通过添加标志来解决这个问题,这些标志描述了响应的ArbiterResponse类型。但我真的不喜欢这个解决方案,因为它是一些手动的,容易出错的工作。谁有更好的主意?

sealed trait ArbiterResponse[+Tasks] {
  def isRejected: Boolean
  def isProceed: Boolean
  def isProceedConditionally: Boolean
}

object Reject extends ArbiterResponse[Nothing] {
  def isRejected = true
  def isProceed = false
  def isProceedConditionally = false
}

trait Proceed[Tasks] extends ArbiterResponse[Tasks] {
  def isRejected = false
  def isProceed = true
  def isProceedConditionally = false
}
object Proceed extends Proceed[Nothing]

case class ProceedConditionally[Tasks](tasks : Tasks) extends Proceed[Tasks] {
  override def isProceedConditionally = true
}

1 个答案:

答案 0 :(得分:1)

在大多数情况下从java调用scala代码非常棘手。但无论如何,如果你想通过打字方式,那么你可以这样做:

    for (Object response : Arrays.asList(new ProceedConditionally("asdf"), Reject$.MODULE$)) {
        if(Reject$.class.isInstance(response)){
            Reject$ cast = Reject$.class.cast(response);
            System.out.println(cast);
        }else if(Proceed.class.isInstance(response)){
            System.out.println("Proceed");
        }else{
            System.out.println("Nothing: "+response.getClass());
        }
    }

打印

  

继续

     

prac.Reject$@266474c2

但它可能会很快打破不同的scala版本,或者将它弄好是很棘手的。一种方法可能是通过访客模式方式。它并不完全令人满意,但可能会有所帮助

sealed trait ArbiterResponse[+Tasks]{
  def doSomething
}

object Reject extends ArbiterResponse[Nothing]{
  def doSomething = ???
}

trait Proceed[Tasks] extends ArbiterResponse[Tasks]
object Proceed extends Proceed[Nothing]{
  def doSomething = ???
}
case class ProceedConditionally[Tasks](tasks : Tasks) extends Proceed[Tasks]{
  def doSomething = println(tasks)
}