加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 案例类的隐式解析和伴随对象

发布时间:2020-12-16 08:43:29 所属栏目:安全 来源:网络整理
导读:我正在尝试向(我认为是)案例类的伴随对象添加隐式值,但是找不到此隐式值. 我正在尝试实现以下内容: package mypackageobject Main { def main(args: Array[String]): Unit = { val caseClassInstance = MyCaseClass("string") val out: DataOutput = ... se
我正在尝试向(我认为是)案例类的伴随对象添加隐式值,但是找不到此隐式值.

我正在尝试实现以下内容:

package mypackage

object Main {
  def main(args: Array[String]): Unit = {
    val caseClassInstance = MyCaseClass("string")
    val out: DataOutput = ...
    serialize(out,caseClassInstance)
    // the above line makes the compiler complain that there is no
    // Serializer[MyCaseClass] in scope
  }
  def serialize[T : Serializer](out: DataOutput,t: T): Unit = {
    ...
  }
}
object MyCaseClass {
  // implicits aren't found here
  implicit val serializer: Serializer[MyCaseClase] = ...
}

case class MyCaseClass(s: String) {
  // some other methods
}

我在这里明确添加了包,以表明MyCaseClass案例类和对象都应该在范围内.我知道该对象实际上正在构建,因为如果我添加,我可以编译它

implicit val serializer = MyCaseClass.serializer

to main(虽然特别是如果我添加import MyCaseClass.serializer).

我担心MyCaseClass对象实际上并不是case类的伴侣,因为如果我在对象上显式定义apply和unapply然后尝试在main中调用MyCaseClass.apply(“string”),编译器会给出以下内容错误:

ambiguous reference to overloaded definition,both method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
and  method apply in object MyCaseClass of type (s: String)mypackage.MyCaseClass
match argument types (String)
val a = InputRecord.apply("string")
                    ^

如果不可能采用这种方法,有没有办法在每次必须将其带入范围时使用带有case类的类型类而不创建隐式值?

编辑:我正在使用scala 2.10.3.

编辑2:以下是充实的例子:

package mypackage

import java.io.{DataOutput,DataOutputStream}

object Main {
  def main(args: Array[String]): Unit = {
    val caseClassInstance = MyCaseClass("string")
    val out: DataOutput = new DataOutputStream(System.out)
    serialize(out,t: T): Unit = {
    implicitly[Serializer[T]].write(out,t)
  }
}
object MyCaseClass {
  // implicits aren't found here
  implicit val serializer: Serializer[MyCaseClass] = new Serializer[MyCaseClass] {
    override def write(out: DataOutput,t: MyCaseClass): Unit = {
      out.writeUTF(t.s)
    }
  }
}

case class MyCaseClass(s: String) {
  // some other methods
}

trait Serializer[T] {
  def write(out: DataOutput,t: T): Unit
}

但这实际上是编译的.我在使用Scoobi的WireFormat [T]而不是Serializer时遇到了这个问题,但由于复杂性和Scoobi依赖性,无法提供简洁,可运行的示例.我将尝试创建一个更相关的示例,但似乎问题并不像我想象的那么普遍.

解决方法

事实证明,类型类实例实际上需要是隐式值,而不是对象.上面的MyCaseClass对象有效,因为它的序列化程序被赋值为隐式值.但是,这个实现

object MyCaseClass {
  implicit object MyCaseClassSerializer extends Serializer[MyCaseClass] {
    override def write(out: DataOutput,t: MyCaseClass): Unit = {
      out.writeUTF(t.s)
    }
  }
}

因错误而失败

Main.scala:9: error: could not find implicit value for evidence parameter of type mypackage.Serializer[mypackage.MyCaseClass]
    serialize(out,caseClassInstance)
             ^

在我的实际代码中,我使用辅助函数来生成Serializer [T](参见https://github.com/NICTA/scoobi/blob/24f48008b193f4e87b9ec04d5c8736ce0725d006/src/main/scala/com/nicta/scoobi/core/WireFormat.scala#L137).尽管函数具有自己的显式返回类型,但编译器未正确推断指定值的类型.

以下是使用此类Serializer-generator的问题的完整示例.

package mypackage

import java.io.{DataOutput,DataOutputStream}

object Main {
  import Serializer._
  def main(args: Array[String]): Unit = {
    val caseClassInstance = MyCaseClass("string")
    val out: DataOutput = new DataOutputStream(System.out)
    serialize(out,caseClassInstance)
  }
  def serialize[T : Serializer](out: DataOutput,t)
  }
}

object MyCaseClass {
  import Serializer._
  // does not compile without Serializer[MyCaseClass] type annotation
  implicit val serializer: Serializer[MyCaseClass] = 
      mkCaseSerializer(MyCaseClass.apply _,MyCaseClass.unapply _)
}

case class MyCaseClass(s: String)

trait Serializer[T] {
  def write(out: DataOutput,t: T): Unit
}

object Serializer {
  // does not compile without Serializer[String] type annotation
  implicit val stringSerializer: Serializer[String] = new Serializer[String] {
    override def write(out: DataOutput,s: String): Unit = {
      out.writeUTF(s)
    }
  }

  class CaseClassSerializer[T,A : Serializer](
      apply: A => T,unapply: T => Option[A]) extends Serializer[T] {
    override def write(out: DataOutput,t: T): Unit = {
      implicitly[Serializer[A]].write(out,unapply(t).get)
    }
  }

  def mkCaseSerializer[T,A : Serializer]
      (apply: A => T,unapply: T => Option[A]): Serializer[T] =
    new CaseClassSerializer(apply,unapply)
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读