使用类型参数进行隐式解析时,为什么 val 放置很重要?

  • 本文关键字:val 类型参数 scala implicit
  • 更新时间 :
  • 英文 :


在一个文件中,我有:

trait JsonSchema[T] {
val propertyType: String
override def toString: String = propertyType
}
object JsonSchema {
implicit def stringSchema: JsonSchema[String] = new JsonSchema[String] {
override val propertyType: String = "string"
}
implicit def intSchema: JsonSchema[Int] = new JsonSchema[Int] {
override val propertyType: String = "integer"
}
implicit def booleanSchema: JsonSchema[Boolean] = new JsonSchema[Boolean] {
override val propertyType: String = "boolean"
}
}

在我的主文件中:

case class MetaHolder[T](v: T)(implicit val meta: JsonSchema[T])
object JsonSchemaExample extends App {
println(MetaHolder(3).meta.toString)
println(MetaHolder("wow").meta.toString)
}

这很笨拙。现在假设我这样做:

case class MetaHolder[T](v: T) {
val meta: JsonSchema[T] = implicitly[JsonSchema[T]]
}

它不再编译。为什么?

我的目标是通过为所有内容添加val meta来修改 scala Finch 库中的匿名Endpoint类。到目前为止,我已经能够在没有任何花哨业务的情况下做到这一点,但现在我想用无形状做一些花哨的隐式解决方案,为任意案例类提供一个JsonSchema定义。我的问题是如何在保持向后兼容性的同时做到这一点。如:为想要选择加入的人提供 jsonschema 元功能,不要改变任何不想使用 meta 的人的编译负担,

如果我走第一条路线,添加隐式参数,那不是需要每个人添加特殊导入吗?还是我错过了什么,是否仍会保持向后兼容性?

参数之间的implicit x: X和体内implicitly[X]有很大的区别。

当您说implicitly[X]时,这意味着"立即检查当前范围内是否存在隐式X"。

当您说def foo(...)(implicit x: X) = ...时,这意味着"稍后在调用foo时检查在调用站点的范围内会有一个隐式X(现在在内部foo只是假设而不检查是否存在("。

class Foo(...)(implicit x: X)类似于后者,"检查何时调用构造函数时是否会有隐式X"。

关于用户是否必须导入。如果将类型X的隐式放入X的伴随对象,则会自动找到它们(类型X[Y]的隐式应放入XY的伴随对象(。如果将它们放在其他地方,则必须将它们导入到当前范围。

为了使implicitly[JsonSchema[T]]进行编译,隐式作用域中必须有一个JsonSchema[T],这意味着必须有一个JsonSchema[T](或可隐式转换为JsonSchema[T]的东西(作为隐式参数传递,就像你所做的那样:

case class MetaHolder[T](v: T)(implicit val meta: JsonSchema[T])

相关内容

  • 没有找到相关文章

最新更新