【问题标题】:Compile error when using a companion object of a case class as a type parameter使用案例类的伴随对象作为类型参数时出现编译错误
【发布时间】:2014-06-17 21:29:17
【问题描述】:

我正在使用案例类在 scala 中创建一些用于喷雾的 json 消息。例如:

  case class Foo(name: String, attrs: List[String])
  implicit val fooFormat = jsonFormat2(Foo)
  object Foo {
    case class Invalid(error: String)
  }
  case class Bar(name: String, kv: Map[String, String])
  implicit val barFormat = jsonFormat2(Bar)

在上面的 sn-p 中,barFormat 编译,但 fooFormat 没有:

type mismatch; found : Foo.type required: (?, ?) => ? 
 Note: implicit value barFormat is not applicable here because it comes 
 after the application point and it lacks an explicit result type

我不想用barFormat代替fooFormat,而且我明白一个case类会自动生成一个伴生对象,但是我不明白为什么这里会出现编译器错误,以及错误信息我很难破译。有谁知道这里的问题是什么以及如何解决它,最好不要删除我的 Foo 伴随对象?

【问题讨论】:

  • 至少给我们jsonFormat2的类型。
  • @downvoter,请解释你的反对意见。
  • @wingedsubmariner,jsonFormat2 的类型相当神秘:def jsonFormat2[P1, P2, T T)(implicit evidence$4: spray.json.DefaultJsonProtocol.JF[P1],implicit evidence$5: spray.json.DefaultJsonProtocol.JF[P2],implicit evidence$6: ClassManifest[T]): spray.json.RootJsonFormat[T]
  • 对不起,我没认出那是喷雾的一部分,我还以为是你写的方法。实际上,它的类型是 def jsonFormat2[A :JF, B :JF, T <: Product :ClassManifest](construct: (A, B) => T): RootJsonFormat[T] - 您可能犯了复制/粘贴错误并删除了 construct

标签: scala spray


【解决方案1】:

从您的编译错误来看,jsonFormat2 需要一个有两个参数的函数。您的意思是将FooBar 的构造函数传递给它吗?如果是这样,您应该使用Foo.applyBar.apply

【讨论】:

  • 同意这是一件令人讨厌的事情,但目前没有更好的解决方法。
  • 我不明白这个答案。 jsonFormat2 的编号应该与案例类的构造函数参数的数量相匹配(它确实如此)。有关 Spray.json 示例,请参阅 here。 @jonderry 的问题解决了吗?
  • @akauppi,这个答案有什么问题?我正在使用Foo.apply 准确地建议您在下面回答的内容
  • 啊,你是对的。在知道正确答案之前,我认为您的意思是将FooBar(或Foo.applyBar.apply)都传递给(可能两者)构造函数,因为他们期待两个参数。你的文字是正确的 - 它说“两个参数函数”(不同的东西)。也许是因为它实际上并没有显示正确的方法,所以我没有认识到解决方案确实是正确的。也许改写或添加我的答案中的代码片段?
  • 实际上存在jsonFormat1jsonFormat22。它匹配案例类的允许构造函数参数。我认为,为了使其更加自动化,需要使用宏。
【解决方案2】:

默认情况下,案例类伴随对象将扩展功能特征之一。 object Foo 会扩展 ((String, List[String]) => Foo) 但是当您手动定义它时,您并没有扩展该特征。这就是为什么你不能将它传递给 jsonFormat2,它期待的是 (?, ?) => ?。如果您进行以下更改,您的代码应该可以编译:

object Foo extends ((String, List[String]) => Foo) {

【讨论】:

    【解决方案3】:

    Spray.json documentation 提出了比@wingedsubmariner 的建议更简单的方法:

    如果您为您的案例类明确声明伴随对象 上面的符号将停止工作。您必须明确提及 伴随对象的 apply 方法来解决这个问题:

    所以问题的更正变成:

    implicit val fooFormat = jsonFormat2(Foo.apply)
    

    补充说:这实际上也是@geoffliu 在他的回答中所建议的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 2013-06-05
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 2017-02-23
      相关资源
      最近更新 更多