1

我正在尝试使用隐式来尝试覆盖我在 ADT 的案例类中拥有的序列化方法,但是我无法理解应该如何完成它

// START OF API//

/**
 * Serialize methods defined here
 *
 */

object Serializer {
  def string(block: (String => String)) = block
  def int(block:(Int => String)) = block
  def double(block:(Double => String)) = block
}

/**
 * These are the DEFAULT serializers
 */

object Implicits {
  implicit val string = Serializer.string (s => s)
  implicit val int = Serializer.int (i => i.toString)
  implicit val double = Serializer.double (d => String.valueOf(d))
}

/**
 *
 * Our simple ADT defined here
 */

import Implicits._

abstract class Vehicle {
  def serialize:String
}

case class Car(s:String) extends Vehicle {
  def serialize: String = string(s)
}

case class Truck(i:Int) extends Vehicle {
  def serialize: String = int(i)
}

case class RocketShip(d:Double) extends Vehicle {
  def serialize: String = double(d)
}

// END OF API

// START OF USER CODE

object UserImplicit {
  implicit val string = Serializer.string(s => s.capitalize)
}

object Main extends App{
  val v = Car("some car")

  println(v.serialize)
  import test.UserImplicit._
  // This SHOULD print a capatilized version i.e. SOME CAR
  println(v.serialize)
}

// END OF USER CODE

基本上我想修补默认的序列化器方法(包含在里面的那些object Implicits),以便 API 的用户可以实现自己的序列化器

我尝试了许多组合(例如在 atrait而不是 a中使用隐含object)但是我实际上并没有设法让它工作

4

2 回答 2

3

我认为您真的想为此使用类型类。方便地,在 Scala 中,您可以根据需要提供自己的(或“覆盖”)。

trait Serializer[A] extends (A => String)

object Serializer {
  def Serializer[A: Serializer] = implicitly[Serializer[A]]
}

trait SerializerInstances {
  implicit val StringSerializer = new Serializer[String] {
    def apply(s: String) = s
  }
  implicit val IntSerializer = new Serializer[Int] {
    def apply(i: Int) = i.toString
  }
  implicit val DoubleSerializer = new Serializer[Double] {
    def apply(i: Int) = i.toString
  }
  implicit def TupleSerializer[A: Serializer, B: Serializer] = new Serializer[(A, B)] {
    def apply(t: (A, B)) = s"(${Serializer[A](a)}, ${Serializer[B](b)})"
  }
}

现在,要使用它们,您只需声明您的代码需要使用一个绑定了 Serializer 上下文的东西:

def somethingThatDoesSerialization[A: Serializer](a: A) = {
  val serializedForm: String = Serializer[A](a)
  …
}

您现在可以导入/管理适合您需要的任何序列化程序集。

于 2013-08-08T01:41:51.370 回答
0

我实际上设法使用皮条客我的库模式来解决这个问题,这是工作代码的示例

object Implicits {
  def defaults(v:Vehicle):String = {
    v match {
      case Car(c) => "This is car " + c
      case Truck(t) => "This is a truct " + t
      case RocketShip(r) => "This is a rocketship " + r
    }
  }

  class VehicleSerializer(v:Vehicle) {
    def serialize:String = defaults(v)
  }

  implicit def vSerialize(v:Vehicle) = new VehicleSerializer(v)
}

/**
 * Our simple ADT defined here
 */
abstract class Vehicle {}
case class Car(s: String) extends Vehicle {}
case class Truck(i: Int) extends Vehicle {}
case class RocketShip(d: Double) extends Vehicle {}

// END OF API

// START OF USER CODE

class UserImplicit(v:Vehicle) {
  def serialize:String = {
    v match {
      case Car(c) => "This is a MASSIVE car " + c
      case _v => Implicits.defaults(_v)
    }

  }
}

object Test extends App {
  val c = Car("rawr")

  // This is the default serializer
  {
    import Implicits._
    println(c.serialize)
  }

  // This is our overwritten serializer
  {
    implicit def vSerialize(v:Vehicle) = new UserImplicit(v)
    println(c.serialize)
  }
}

// END OF USER CODE

哪个打印

This is car rawr
This is a MASSIVE car rawr

如预期

于 2013-08-08T08:25:07.233 回答