2017-07-20 2 views
2

私は以下のScalaの階層ました:scalaオブジェクトでinstanceofを使用するにはどうすればよいですか?

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を使用して、スカラのオブジェクトのクラスを確認するにはどうすればよいですか?

私は取得していますエラーは次のとおりです。

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

なぜそれは正確にコンパイルされませんか?あなたがすでに 'sr instanceof SessionResult ' – XtremeBaumer

+0

@XtremeBaumerを取得していることを知っているので、私は推測します。_Inconvertible types; SessionResult をNoSession_にキャストできません。 – Opal

+0

次に、前のコメントで私が次に言ったことを見てください。私はそれが理由だと確信しています – XtremeBaumer

答えて

4

問題は、一般的なパラメータにハードバウンドを入れているという事実にある - NoSessionSessionResult[Nothing]です。

SessionResult.NoSession$に対応するSessionResult<T>の唯一の互換性のあるバリアントは、SessionResult<Nothing$>です。これはコンパイルされ

すなわち

public SessionResult<Nothing$> test() { 

    return null; 
} 

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

例えば、一方

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

equalsが原因あなたがアップキャストする必要が変動するとして必要とされる:NoSessionは、したがって、あなただけの参照、テストすることができシングルトン値を、objectあるので、これは、幸いなことではない

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

    return null; 
} 

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

ますObject - あなたは手動で行うが、あなたにその上のいくつかの時間を節約することができますequals


A lternatively、あなただけの選択すなわち、一般的なパラメータをワイルドカードことができます。:

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$); 
} 

これは非常にハック解決策が、ほとんどのJavaでこのような平等のチェックを扱うコードのため、おそらく最も便利です。 testNay3に示されているように、単純なインプレースキャストを使用して、このようにジェネリック型を使用する場合の「付随的な損害」を制限することができます。

編集:は、Alexey'sヒントごとにワイルドカードに変更されました。

+3

私は 'SessionResult 'を生の 'SessionResult'にすることをお勧めします。 –

+0

@AlexeyRomanov:arghh、Javaワイルドカードについて完全に忘れてしまった!ヒントありがとう! –

関連する問題