如何在scala对象中使用instanceof?

时间:2017-07-20 13:40:17

标签: java scala instanceof

我有以下scala层次结构:

sealed trait SessionResult[+T] {
  def toOption: Option[T]
}

object SessionResult {
  trait SessionValue[T] extends SessionResult[T] {
    def session: T
    def toOption: Option[T] = Some(session)
  }
  trait NoSessionValue[T] extends SessionResult[T] {
    def toOption: Option[T] = None
  }

  case class Decoded[T](session: T) extends SessionResult[T] with SessionValue[T]
  case class CreatedFromToken[T](session: T) extends SessionResult[T] with SessionValue[T]

  case object NoSession extends SessionResult[Nothing] with NoSessionValue[Nothing]
  case object TokenNotFound extends SessionResult[Nothing] with NoSessionValue[Nothing]
  case object Expired extends SessionResult[Nothing] with NoSessionValue[Nothing]
  case class Corrupt(e: Exception) extends SessionResult[Nothing] with NoSessionValue[Nothing]
}

但是我使用java中的代码并且下面的代码不能编译:

SessionResult<SomeSession> sr = ...
System.out.println(sr instanceof NoSession)

为什么呢?还有我如何使用instanceof检查scala对象的类?

我得到的错误是:

Inconvertible types; cannot cast SessionResult<SomeSession> to NoSession.

1 个答案:

答案 0 :(得分:4)

问题在于您对通用参数设置了严格限制 - NoSessionSessionResult[Nothing]

所以(用Java术语),与SessionResult<T>兼容的SessionResult.NoSession$的唯一兼容变体可以是SessionResult<Nothing$>

即。这将编译

public SessionResult<Nothing$> test() {

    return null;
}

public void blah() {
    if(test() instanceof SessionResult.NoSession$) {
    }
}
例如,

这不会

public <T> SessionResult<T> test() {

    return null;
}

public void blah() {
    if(test() instanceof SessionResult.NoSession$) {
    }
}

幸运的是,由于NoSessionobject,因此您可以参考测试单例值:

SessionResult.NoSession$.MODULE$.equals(test());

equals是必需的,因为您需要将广告转换为Object - 您可以手动执行此操作,但equals会为您节省一些时间)

或者,您可以选择性地对通用参数进行通配符,即:

public static SessionResult<?> testYay() {
    return SessionResult.NoSession$.MODULE$;
}

public static SessionResult<?> testNay1() {
    return null;
}

public static SessionResult<?> testNay2() {
    return SessionResult.Expired$.MODULE$;
}

public static <T> SessionResult<T> testNay3() {
    return null;
}

public static void blah() {
    //prints true
    System.out.println(testYay() instanceof SessionResult.NoSession$);
    //prints false
    System.out.println(testNay1() instanceof SessionResult.NoSession$);
    //prints false
    System.out.println(testNay2() instanceof SessionResult.NoSession$);
    //prints false (and compiles)
    System.out.println((SessionResult<?>) testNay3() instanceof SessionResult.NoSession$);
}

这是一个非常hacky的解决方案,但对于主要处理Java中的此类相等性检查的代码而言,这可能是最方便的。正如testNay3中所示,您可以通过简单的就地演员来限制使用泛型类型的“附带损害”。

编辑: 根据Alexey's提示更改为通配符。