0

次の構造化型に従う ADT データ型の一般化されたシリアライザーを作成しようとしています。

  /**
   * Our standard ADT representation, indexed by ID. ADT's also have a formattedString (formal name representing ADT)
   */
  type ADT = {def id: Long; def formattedName:String}
  /**
   * This is a structured type that forces the companion objects associated with an ADT to have an all value. This all
   * value is an enumeration of all of the sum types of the ADT, and is generated by a macro
   * @tparam A
   */
  type ADTCompanion[A] = {val all:Set[A]}

また、ADT を処理するためのヘルパー関数も作成しました。つまり、

  /**
   * Look up an sum type by its id
   * @param companion The companion object being looked up
   * @param id The id to look up
   * @tparam A The type of the companion object
   * @return The corresponding sum type
   */

  def getADT[A <: ADT](companion:ADTCompanion[A], id:Long) = {
    var re:Option[A] = None
    try {
      for (item <- companion.all) {
        if (item.id == id) {
          re = Some(item)
        }
      }
      re.getOrElse(throw new InvalidId(companion,id))
    } catch {
      case e:Throwable => throw new InvalidId(companion,id)
    }
  }

  /**
   * Look up a sum type by its formattedName
   * @param companion The companion object being looked up
   * @param formattedName The formattedName to look up
   * @tparam A The type of the companion object
   * @return The corresponding sum type
   */

  def getADT[A <: ADT](companion:ADTCompanion[A], formattedName:String) = {
    var re:Option[A] = None
    try {
      for (item <- companion.all) {
        if (item.formattedName == formattedName) {
          re = Some(item)
        }
      }
      re.getOrElse(throw new InvalidFormattedName(companion,formattedName))
    } catch {
      case e:Throwable => throw new InvalidFormattedName(companion,formattedName)
    }
  }

今私の問題は次のとおりです

  private def jsonADTSerializer[A <: ADT](adtName:String,adt:ADTCompanion[A]):(PartialFunction[JValue, A], PartialFunction[Any,JValue]) = (
    {
      case JObject
        (JField
          (`adtName`,
            JObject(List(JField("id",JString(id)),JField("formattedName",formattedName)))) :: _) => getADT(adt,id.toLong)
    },
    {
      case x: A => {
        adtName -> (
          ("formattedName" -> x.formattedName) ~
            ("id" -> x.id)
          )
      }
    }
  )

  sealed abstract class Test(val id: Long,val formattedName:String)
  case object Test1 extends Test(1,"Test 1")
  case object Test2 extends Test(2,"Test 2")

  object Test {
    val all:Set[Test] = SealedContents.values[Test]
  }

  sealed abstract class Foo(val id:Long, val formattedName:String)
  case object Foo1 extends Foo(1,"Foo 1")

  object Foo {
    val all:Set[Foo] = SealedContents.values[Foo]
  }

  class TestSerializer extends CustomSerializer[Test](format => jsonADTSerializer("Test",Test))
  class FooSerializer extends CustomSerializer[Foo](format => jsonADTSerializer("Foo",Foo))

ご覧のとおり、ADT をシリアル化する際に jsonADTSerializer 関数を使用してボイラープレートを削減しようとしていますが、上記のコードをコンパイルすると、次の警告メッセージが表示されます。

42: abstract type pattern A is unchecked since it is eliminated by erasure
[warn]       case x: A => {

そして、当然のことjava.lang.NoSuchMethodExceptionながら、上記のコードを使用するとエラーが発生します ( A が消去されているため、 がすべてを取得しているため、型に準拠していないcase:xクラスが取り込まれます)。jsonADTSerializerA

関数が意図したとおりに機能するように、A内部の型が消去されないようにするにはどうすればよいですか?jsonADTSerializer

また、疑問に思っている場合は、https://stackoverflow.com/a/13672520/1519631で見つけることができる封印されたコンテンツ マクロを使用しています。

scalatra の json シリアル化に関する情報は、http://www.scalatra.org/guides/formats/json.html にあります

更新 : の typetage を変更して、消去に関する警告メッセージjsonADTSerializerを削除し、問題を修正しました。ありがとう!private def jsonADTSerializer[A <: ADT : ClassTag](adtName:String,adt:ADTCompanion[A]):(PartialFunction[JValue, A], PartialFunction[Any,JValue]) = (

4

1 に答える 1

1

ClassTagContext Bound をメソッド定義に追加するだけでよいと思います。

import scala.reflect._
private def jsonADTSerializer[A <: ADT : ClassTag](adtName:String,adt:ADTCompanion[A]):(PartialFunction[JValue, A], PartialFunction[Any,JValue]) = (

...rest as before...
于 2013-10-25T16:09:15.727 に答える