2016-10-23 18 views
0

マップの定義の一部として渡されるジェネリック型を使用する関数を使用しようとしています。クラスを拡張する汎用型の関数

EventBaseから延長としてsetMappingに私はTを定義し、setMapping呼出し - 私の定義クラスタイプI以来ので、ここに私のコード

object EventMapping { 


    val eventMapping = collection.mutable.Map[Class[_ <: EventBase], (User, EventBase) => Unit]() 

    setMapping(classOf[UserCreated], (user, evt) => user.loadUserName(evt.userName)) 


    private def setMapping[T <: EventBase](clazz: Class[T],fn: (User, T) => Unit) { 
    eventMapping += clazz -> fn.asInstanceOf[(User, EventBase) => Unit] 
    } 

} 

UserCreatedクラスは、EventBaseから伸びる専用のイベントクラスであります、使用して機能

user.loadUserName(evt.userName)) 

に私はEVTはそれがCreatedUserイベントとして考慮されることを期待していたが、それでもコンパイラはEventBaseとして検討しています。

Javaの同様のコードベースが動作しますが、私はここで何が欠けているのか分かりません。ここで

UserCreatedクラス

class UserCreated @JsonCreator() (@JsonProperty("userName")val userName: String) extends EventBase{ 


    @JsonProperty("userName") def getUserName: String = { 
    userName 
    } 
} 

これは、問題はsetMappingの定義では、あなたはTEventBaseのサブタイプであることだけをコンパイラを言っているということであるスタックトレース

[info] Compiling 5 Scala sources to /Development/proyectX/target/scala-2.11/classes... 
[error] /Development/proyectX/app/persistance/EventMapping.scala:11: missing parameter type 
[error] setMapping(classOf[UserCreated], (user, evt) => user.loadUserName(evt.asInstanceOf[UserCreated].userName)) 
[error]           ^
[error] one error found 
[error] (compile:compile) Compilation failed 
+0

エラーは何ですか?コンパイラエラーメッセージを投稿できますか? – Yawar

+0

私はスタックトレースを追加 – paul

答えて

3

です。だからsetMappingを呼び出すときにevt.userNameがあると、コンパイラはEventBaseのすべてのサブタイプがuserNameのメンバーをサポートすることを保証できないため、コンパイルエラーです。したがって、evt.asInstanceOf[UserCreated].userNameを実行すると、evtが実際にUserCreatedであり、userNameのメンバーをサポートしていることがコンパイラに個人的に保証されています。

第二に、missing parameter typeコンパイルエラー(ないスタックトレースところで、スタックトレースがランタイム例外からのみです)はScalaの型推論アルゴリズムは完璧ではないという結果です。今コンパイラが推測することができるので、これはまたevt.asInstanceOf[UserCreated]をダウンキャストする必要性を除去します

object EventMapping { 
    val eventMapping = 
    collection.mutable.Map[Class[_ <: EventBase], (User, EventBase) => Unit]() 

    setMapping(classOf[UserCreated]) { (user, evt) => 
    user.loadUserName(evt.userName) 
    } 

    private def setMapping[T <: EventBase](
    clazz: Class[T])(fn: (User, T) => Unit): Unit = 
    eventMapping += clazz -> fn.asInstanceOf[(User, EventBase) => Unit] 
} 

:アルゴリズムで癖のあるので、あなたは、独自のパラメータリストにマッピング機能(fn)を動かすことで、それは、より正確に行うことができますそれは適切です。

最後に、型推論機能では、すべての行を正しく並べ替えることができず、コンパイルエラーが発生することがあります。その場合、あなただけ明示的に型引数を渡すことがあります。

setMapping[UserCreated](classOf[UserCreated]) { (user, evt) => 
    user.loadUserName(evt.userName) 
} 

をこれはどこでもあなたがジェネリック型Tを持って、この呼び出しでUserCreatedでそれを置き換えるコンパイラに指示します。

P.S.あなたがダウンキャストしなければならないという事実は、通常、より慣用的で構成可能なScalaの機能である型式を使用することができるという印です。

+0

それは私が見逃したキーだったsetMapping [UserCreated]ありがとう! – paul

関連する問題