3

プロジェクトでエンティティとサービスを管理するための一般的なコードがいくつかあり、昨日奇妙な問題に遭遇しました。私はこれに切り取ってミニファイすることができました:

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()、これがこの問題を引き起こしている理由はわかりません。

4

0 に答える 0