在我们的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
}
答案 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)
}