如何将 instanceof 与 scala 对象一起使用?
How to use instanceof with scala object?
我有以下 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 对象的 class?
我得到的错误是:
Inconvertible types; cannot cast SessionResult<SomeSession> to NoSession.
问题在于您对通用参数设置了硬性限制 - NoSession
是 SessionResult[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$) {
}
}
幸运的是,由于 NoSession
是一个 object
,因此您可以只引用测试单例值:
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
中所示,您可以通过简单的就地转换限制 "collateral damage" 以这种方式使用泛型类型。
编辑: 根据 Alexey's 提示更改为通配符。
我有以下 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 对象的 class?
我得到的错误是:
Inconvertible types; cannot cast SessionResult<SomeSession> to NoSession.
问题在于您对通用参数设置了硬性限制 - NoSession
是 SessionResult[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$) {
}
}
幸运的是,由于 NoSession
是一个 object
,因此您可以只引用测试单例值:
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
中所示,您可以通过简单的就地转换限制 "collateral damage" 以这种方式使用泛型类型。
编辑: 根据 Alexey's 提示更改为通配符。