隐式转换不适用
Implicit conversion not applying
我正在尝试练习将任意值转换为它们的 Json 表示的经典示例,并且在未定义转换的情况下出现编译时错误。
到目前为止,我有,
trait Json
trait ConvertableToJson[A] {
def toJson: Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
case class StrToJson(s: String) extends ConvertableToJson[StrToJson] {
override def toJson: Json = Str(s)
}
}
implicit def str2Json(s: String): StrToJson = StrToJson(s)
def toJson[A <: ConvertableToJson[A]](a: A) = a.toJson
println(toJson("some string"))
我希望上面的代码能像这样工作:
toJson("some string")
在没有 implicit def
的情况下无法编译。因为 String <: ConvertableToJson[String]
是假的。
但随后要使用 implicit def
并找到 Str2Json
。
Str2Json <: ConvertableToJson[Str2Json]
应该是真的。
然而,这并没有发生并且编译器抱怨:
Error: Inferred type arguments [String] do not conform to method toJson's type parameter bounds [A <: scalaz.ConvertToJson.ConvertableToJson[A]]
println(toJson("dhruv"))
^
如果有人能帮我纠正我的理解就太好了
所以你的代码有两个问题。首先 String
没有扩展 ConvertableToJson[String]
,这是你最后一个函数调用试图做的。
第二个 case class StrToJson
应该扩展 ConvertableToJson[String]
而不是 ConvertableToJson[StrToJson]
。
然后使用视图边界 <%
编译您的代码(参见下面的工作示例)。然而,这是一个坏主意,因为视图边界已被弃用为一种语言功能,您应该改用类型 类。
trait Json
trait ConvertableToJson[A] {
def toJson: Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
case class StrToJson(s: String) extends ConvertableToJson[String] {
override def toJson: Json = Str(s)
}
}
import Json._
implicit def str2Json(s: String): StrToJson = StrToJson(s)
def toJson[A <% ConvertableToJson[A]](a: A) = a.toJson
println(toJson("some string"))
使用类型类
trait Json
trait ConvertableToJson[A] {
// NOTE: this now takes a parameter
def toJson(a: A): Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
}
import Json._
// NOTE: Because toJson takes a parameter the implicit implementation can now be an object
implicit object Str2Json extends ConvertableToJson[String] {
override def toJson(a: String): Json = Str(a)
}
// NOTE: If you want to support the a.toJson syntax this implicit class adds it for all types with an implicit ConvertableToJson
implicit class ConvertableToJsonSyntax[A](a: A)(implicit ev: ConvertableToJson[A]) {
def toJson: Json = ev.toJson(a)
}
// NOTE: Now we use context-bounds instead of view-bounds
def toJson[A : ConvertableToJson](a: A) = a.toJson
// NOTE: we can expand the context-bounds
def toJson2[A](a: A)(implicit ev: ConvertableToJson[A]) = a.toJson
// NOTE: But since we have the type class instance now, we do not need the extra syntax
def toJson3[A](a: A)(implicit ev: ConvertableToJson[A]) = ev.toJson(a)
println(toJson("some string"))
我正在尝试练习将任意值转换为它们的 Json 表示的经典示例,并且在未定义转换的情况下出现编译时错误。
到目前为止,我有,
trait Json
trait ConvertableToJson[A] {
def toJson: Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
case class StrToJson(s: String) extends ConvertableToJson[StrToJson] {
override def toJson: Json = Str(s)
}
}
implicit def str2Json(s: String): StrToJson = StrToJson(s)
def toJson[A <: ConvertableToJson[A]](a: A) = a.toJson
println(toJson("some string"))
我希望上面的代码能像这样工作:
toJson("some string")
在没有 implicit def
的情况下无法编译。因为 String <: ConvertableToJson[String]
是假的。
但随后要使用 implicit def
并找到 Str2Json
。
Str2Json <: ConvertableToJson[Str2Json]
应该是真的。
然而,这并没有发生并且编译器抱怨:
Error: Inferred type arguments [String] do not conform to method toJson's type parameter bounds [A <: scalaz.ConvertToJson.ConvertableToJson[A]]
println(toJson("dhruv"))
^
如果有人能帮我纠正我的理解就太好了
所以你的代码有两个问题。首先 String
没有扩展 ConvertableToJson[String]
,这是你最后一个函数调用试图做的。
第二个 case class StrToJson
应该扩展 ConvertableToJson[String]
而不是 ConvertableToJson[StrToJson]
。
然后使用视图边界 <%
编译您的代码(参见下面的工作示例)。然而,这是一个坏主意,因为视图边界已被弃用为一种语言功能,您应该改用类型 类。
trait Json
trait ConvertableToJson[A] {
def toJson: Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
case class StrToJson(s: String) extends ConvertableToJson[String] {
override def toJson: Json = Str(s)
}
}
import Json._
implicit def str2Json(s: String): StrToJson = StrToJson(s)
def toJson[A <% ConvertableToJson[A]](a: A) = a.toJson
println(toJson("some string"))
使用类型类
trait Json
trait ConvertableToJson[A] {
// NOTE: this now takes a parameter
def toJson(a: A): Json
}
object Json {
case class Str(str: String) extends Json
case class Int(int : Int) extends Json
}
import Json._
// NOTE: Because toJson takes a parameter the implicit implementation can now be an object
implicit object Str2Json extends ConvertableToJson[String] {
override def toJson(a: String): Json = Str(a)
}
// NOTE: If you want to support the a.toJson syntax this implicit class adds it for all types with an implicit ConvertableToJson
implicit class ConvertableToJsonSyntax[A](a: A)(implicit ev: ConvertableToJson[A]) {
def toJson: Json = ev.toJson(a)
}
// NOTE: Now we use context-bounds instead of view-bounds
def toJson[A : ConvertableToJson](a: A) = a.toJson
// NOTE: we can expand the context-bounds
def toJson2[A](a: A)(implicit ev: ConvertableToJson[A]) = a.toJson
// NOTE: But since we have the type class instance now, we do not need the extra syntax
def toJson3[A](a: A)(implicit ev: ConvertableToJson[A]) = ev.toJson(a)
println(toJson("some string"))