【问题标题】:Using implicit methods inside case classes ADT在案例类 ADT 中使用隐式方法
【发布时间】:2013-08-07 08:03:13
【问题描述】:

我正在尝试使用隐式来尝试覆盖我在 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 个 println(v.serialize) 调用打印 2 个不同的字符串,第一个是 "some car"",因为它使用的是 object Implicits 中的版本,并且第二个"SOME CAR",因为它使用UserImplicit 中的版本,该版本将字符串大写(即implicit val string = Serializer.string(s => s.capitalize)
  • 在 Scala 中的 ADT 应该被编码为 sealed trait 结合 case objects 和 sealed case classes。

标签: scala implicit monkeypatching abstract-data-type


【解决方案1】:

我认为您真的想为此使用类型类。方便的是,在 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)
  …
}

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

【讨论】:

    【解决方案2】:

    我实际上设法使用 pimp my library 模式解决了这个问题,这是一个工作代码示例

    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
    

    按照预期

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      • 1970-01-01
      • 2014-06-21
      • 2011-07-29
      • 2020-12-04
      • 2013-05-31
      相关资源
      最近更新 更多