プロジェクトでエンティティとサービスを管理するための一般的なコードがいくつかあり、昨日奇妙な問題に遭遇しました。私はこれに切り取ってミニファイすることができました:
object Test extends App {
trait Id extends Any {
def id: Int
}
trait EntityWithId[I] {
def id: Option[I]
}
case class UserId(id: Int) extends AnyVal with Id
case class User(id: Option[UserId], password: String) extends EntityWithId[UserId]
trait BaseService[I <: Id, E <: EntityWithId[I]] {
def save(entity: E): I = entity.id.get // mock
}
trait UserService extends BaseService[UserId, User] {
def encrypt(pass: String): String = pass // mock
def encryptAndSave(user: User): UserId =
super.save(user.copy(password = encrypt(user.password)))
}
object UserService extends UserService
val user1 = User(Some(UserId(1)), "jerzy")
val user2 = User(Some(UserId(2)), "jerzy")
UserService.save(user1) // passes
UserService.encryptAndSave(user2) // fails
}
encryptAndSave
奇妙な例外からメソッドを使用しようとすると、UserService
スローされます:
Exception in thread "main" java.lang.ClassCastException: controllers.Test$UserId cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
at controllers.Test$UserService$.controllers$Test$UserService$$super$save(Test.scala:32)
at controllers.Test$UserService$class.encryptAndSave(Test.scala:29)
at controllers.Test$UserService$.encryptAndSave(Test.scala:32)
at controllers.Test$delayedInit$body.apply(Test.scala:38)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.collection.immutable.List.foreach(List.scala:309)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
at scala.App$class.main(App.scala:71)
at controllers.Test$.main(Test.scala:8)
at controllers.Test.main(Test.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
super.save()
に変更するだけでなんとか修正できましたがthis.save()
、これがこの問題を引き起こしている理由はわかりません。