2

私は単純なケースクラスを持っています:

object Margin {
  def apply(top: Int, right: Int, bottom: Int, left: Int): Margin = {
    Margin(Some(top), Some(right), Some(bottom), Some(left))
  }
}

case class Margin(top: Option[Int], right: Option[Int], bottom: Option[Int], left: Option[Int])

上記のクラスのインスタンスを呼び出すupickle.writeと、次の例外が発生します。

scala.ScalaReflectionException: value apply encapsulates multiple     
overloaded alternatives and cannot be treated as a method. Consider 
invoking `<offending symbol>.asTerm.alternatives` and manually picking 
the required method

このエラー メッセージの意味と修正方法を教えてください。

4

1 に答える 1

1

上記のエラー メッセージは、複数のオーバーロードされたメソッドMarginを持つクラスの結果です。apply1 つはケース クラスのコンストラクターで、もう 1 つはコンパニオン オブジェクトにあります。Upickle はどのメソッドを使用すればよいかわからないapplyため、この例外をスローします。これは既知の制限です。

apply1 つの回避策は、コンパニオン オブジェクトにあるメソッドの名前を変更することです。もう 1 つは、カスタム picklerを作成することです。

これは、問題を解決したカスタム ピックラーのやや不器用なバージョンです。

object Margin {
  def create(top: Int, right: Int, bottom: Int, left: Int): Margin = {
    Margin(Some(top), Some(right), Some(bottom), Some(left))
  }

  implicit val marginWriter = upickle.Writer[Margin]{
    case m =>
      Js.Obj(fields(m).map(kv => (kv._1, Js.Num(kv._2))):_*).asInstanceOf[Js.Value]
  }

  implicit val marginReader = upickle.Reader[Margin]{
    case obj: Js.Obj =>
      val map = obj.value.toMap
      Margin(map.get("top").map(_.value.asInstanceOf[Int]),
        map.get("right").map(_.value.asInstanceOf[Int]),
        map.get("bottom").map(_.value.asInstanceOf[Int]),
        map.get("left").map(_.value.asInstanceOf[Int]))
  }

  private def fields(m: Margin) = Seq(m.top.map(("top", _)), m.right.map(("right", _)), m.bottom.map(("bottom", _)),
    m.left.map(("left", _))).flatten
}
于 2015-06-10T18:44:24.443 に答える