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

Scala中抽象类型参数的隐式转换

发布时间:2020-12-16 10:02:39 所属栏目:安全 来源:网络整理
导读:我是 Scala的新手,探索隐式转换和着名蛋糕模式的可能性.我尝试创建模型类,其id值列为抽象类型,以避免泄漏实现细节.我也把它混合成蛋糕模式特质包装.一切正常,除了从id到 JSON的隐式转换(在Play框架内).无论我做什么,Scala编译器都找不到隐式转换. 这是重现问
我是 Scala的新手,探索隐式转换和着名蛋糕模式的可能性.我尝试创建模型类,其id值列为抽象类型,以避免泄漏实现细节.我也把它混合成蛋糕模式特质包装.一切正常,除了从id到 JSON的隐式转换(在Play框架内).无论我做什么,Scala编译器都找不到隐式转换.

这是重现问题的代码:

import anorm._
import play.api.libs.json._

trait Card {
  type Key
  val NoId: Key
  val id: Key
  val name: String
}

trait CardModelComponent {
  val cardModel: CardModel
  trait CardModel {
    def findById(id: Long): Option[Card]
    def findAll: Seq[Card]
    def delete(id: Long)
    def create(name: String): Option[Card]
  }
}

trait CardModelComponentImpl extends CardModelComponent {
  case class CardImpl(id: Pk[Long],name: String) extends Card {
    type Key = Pk[Long]

    object Key extends Writes[Key] {
      implicit def writes(key: Key): JsValue = {
        key match {
          case Id(idVal: Long) => JsNumber(idVal)
          case _ => JsNull
        }
      }
    }
    val NoId = NotAssigned
  }

  class CardModelImpl extends CardModel {
    def findById(id: Long): Option[Card] = { None }
    def findAll: Seq[Card] = { Seq(CardImpl(Id(1),"Some card"))}
    def delete(id: Long) {}
    def create(name: String): Option[Card] = { Some(CardImpl(Id(1),name)) }
  }
}

object ComponentsRegistry extends
CardModelComponentImpl {

  val cardModel = new CardModelImpl
}

val card = ComponentsRegistry.cardModel.create("Test card").get
Json.toJson(card.id)

我得到的错误输出如下:

> card: Card = CardImpl(1,Test card)
> <console>:19: error: No Json deserializer found for type card.Key. Try to implem
  ent an implicit Writes or Format for this type.
                Json.toJson(card.id)
                           ^

有没有办法使它工作?看起来像蛋糕模式包装隐藏了太多来自编译器的类型信息,我想从card.Key类型名称.

我还尝试直接为Pk创建Writer实现,结果出现相同的错误.

解决方法

就像Je??sper Nordenberg写的那样,你必须将Writes [Key]的实例纳入范围.这样做的一种方法是要求Card的实现发布Writer实例,然后导入你调用toJson的那个,如下所示:

trait Card {
  type Key

  val NoId: Key
  val id: Key
  val name: String
  implicit val Key: Writes[Key]
}

trait CardModelComponentImpl extends CardModelComponent {
  case class CardImpl(id: Pk[Long],name: String) extends Card {
    type Key = Pk[Long]

    implicit object Key extends Writes[Key] {
      def writes(key: Key): JsValue = {
        key match {
          case Id(idVal: Long) => JsNumber(idVal)
          case _ => JsNull
        }
      }
    }

    val NoId = NotAssigned
  }

  class CardModelImpl extends CardModel {
    def findById(id: Long): Option[Card] = { None }
    def findAll: Seq[Card] = { Seq(CardImpl(Id(1),name)) }
  }
}

val card = ComponentsRegistry.cardModel.create("Test card").get
import card.Key
Json.toJson(card.id)

或明确传递:

val card = ComponentsRegistry.cardModel.create("Test card").get
Json.toJson(card.id)(card.Key)

(编辑:李大同)

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

    推荐文章
      热点阅读