在案例类ADT中使用隐式方法

时间:2013-08-07 08:03:13

标签: scala implicit monkeypatching abstract-data-type

我试图使用implicits尝试覆盖我在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的用户可以实现自己的序列化程序

我尝试了很多种组合(例如在trait而不是object中有隐含的内容)但是我实际上没有设法使其正常工作

2 个答案:

答案 0 :(得分: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)})"
  }
}

现在,要使用它们,您只需声明您的代码需要采用具有Seri​​alizer上下文绑定的东西:

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

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

答案 1 :(得分:0)

我实际上设法使用pimp我的库模式来解决它,这是一个工作代码的例子

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

按预期