Scala隐式类型约束的应用与总结

《从JAVA到Scala(三):implicit的三种用法》中,详细地说明了“implicit”关键字的用法,但在实际中,它们可能结合使用为一种模式,比如play框架的JSON用法

//  在JSON化实例之前,必须定义隐式类型Writes[Location]
implicit val locationWrites = new Writes[Location] {
  def writes(location: Location) = Json.obj(
    "lat" -> location.lat,
    "long" -> location.long
  )
}
//  有代码省略
//  得到JsValue对象就可以进行JSON串行化了
val json = Json.toJson(place)

首先吐槽一下,用惯了Spring MVC与Jackson ObjectMapper,初次很不习惯,转个JSON还需要这么多工作?谁说JAVA的代码就一定比Scala多?(PS:其实是我们被Spring框架惯坏了。)

分析其代码,我们发现,我们要串行化对象,必须首先要将其转换为JsValue对象,源码如下:

def stringify(json: JsValue): String =
    StaticBinding.generateFromJsValue(json, false)

怎样得到JsValue对象呢,当然靠Json.toJson方法,源码如下:

def toJson[T](o: T)(implicit tjs: Writes[T]): JsValue = tjs.writes(o)

这是一个高阶隐式类型约束函数(请看implicit的第一种用法),意思是参数o的类型为T,且在调用toJson(o)方法时,必须有隐式值Writes[T]存在,具体到第一段代码,后端调用的完整方法如下:

Json.toJson(place)(
    new Writes[Location] {
      def writes(location: Location) = Json.obj(
        "lat" -> location.lat,
        "long" -> location.long
      )
    }
)

Json.toJson方法还有另外一种写法(参考自《Scala In Depth》),如下:

//  少一个参数,无法写出实现
//  请高手指点
def toJson[T: Writes](o: T)

自定义隐式类型约束

第一步,定义特质,如下:

trait ToInt[T] {
  // 自定义签名  
  def toInt(entity: T): Int
}

第二步,定义方法,包含对特质的引用,如下:

 def toInt[A](x: A)(implicit y: ToInt[A]) = y.toInt(x)

第三步,创建隐式对象,如下:

implicit val tp = new ToInt[Person] {
  override def toInt(entity: Person): Int = entity.age
}

最后,调用即可,如下:

val p = new Person("yiifaa", 32)
//  直接打印
println(toInt(p))

整合

如果按照上述的写法,在每次调用的时候都需要声明一个隐式类型变量,不仅导致了大量的重复,而且也太丑了,这时候就可以利用伴生对象来改进代码质量,如下:

package domain

import play.api.libs.json.{JsValue, Json, Writes}

case class Person(username:String, age:Int)
//  声明伴生对象
object Person {
  //  不要省略implicit关键字
  implicit val PersonToJson = new Writes[Person] {
    override def writes(o: Person): JsValue = Json.obj(
      "username" -> o.username,
      "age" -> o.age
    )
  }
}

现在只需要引入“Person”即可自行转换,如下:

def show(id: Long) = Action {
    import domain.Person
    val out = Json.toJson(new Person("yiifaa", 32))
    Ok(out).as("application/json")
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值