Scala 隐式转换(字符串到自定义 class 及其子class)
Scala implicit conversion(String to a custom class and its subclass)
这是代码,
trait TestBase{}
class TestA(str:String) extends TestBase
class TestB(str:String) extends TestBase
class TestC(str:String) extends TestBase
implicit def mystr2TestA(str:String):TestA = {println(str);null.asInstanceOf[TestA]}
implicit def mystr2TestB(str:String):TestB = {println(str);null.asInstanceOf[TestB]}
implicit def mystr2TestC(str:String):TestC = {println(str);null.asInstanceOf[TestC]}
val testA:TestA = "abc"
val testB:TestB = "abc"
val testC:TestC = "abc"
问题是如何用更优雅高效的代码创建从String
到TestBase
及其子类的隐式转换?(也许只有一个隐式函数?)This is the Code I run in Scala REPL
您可以像这样将其重写为一个隐式定义。
implicit def conv[A <: TestBase](str: String): A = {println(str); null.asInstanceOf[A] }
但是根据您真正的尝试,可能有比将所有 Strings
转换为任何 TestBase
.[=18 更好的解决方案=]
编辑:
出于某种原因,Scala 在选择隐式转换时似乎没有考虑类型约束。它变得更加奇怪:
scala> implicit def bla2Test[A](str: String)(implicit ev: A <:< TestBase): A = null.asInstanceOf[A]
warning: there were 1 feature warning(s); re-run with -feature for details
bla2Test: [A](str: String)(implicit ev: <:<[A,TestBase])A
scala> val notTest: NotTest = "str"
notTest: NotTest = null
scala> implicitly[NotTest <:< TestBase]
<console>:15: error: Cannot prove that NotTest <:< TestBase.
implicitly[NotTest <:< TestBase]
^
因此编译器向 bla2Test
提供了一个 NotTest <:< TestBase
的实例,但不存在实例。
当你想检查类型时 A
:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> implicit def bla2Test[A <: TestBase](str: String)(implicit tag: TypeTag[A]): A = { println(tag); null.asInstanceOf[A] }
warning: there was one feature warning; re-run with -feature for details
bla2Test: [A <: TestBase](str: String)(implicit tag: reflect.runtime.universe.TypeTag[A])A
scala> val notTest: NotTest = "str"
<console>:21: error: type mismatch;
found : String("str")
required: NotTest
val notTest: NotTest = "str"
^
scala> val notTest: TestBase = "str"
<console>:20: error: macro has not been expanded
val notTest: TestBase = "str"
^
这是代码,
trait TestBase{}
class TestA(str:String) extends TestBase
class TestB(str:String) extends TestBase
class TestC(str:String) extends TestBase
implicit def mystr2TestA(str:String):TestA = {println(str);null.asInstanceOf[TestA]}
implicit def mystr2TestB(str:String):TestB = {println(str);null.asInstanceOf[TestB]}
implicit def mystr2TestC(str:String):TestC = {println(str);null.asInstanceOf[TestC]}
val testA:TestA = "abc"
val testB:TestB = "abc"
val testC:TestC = "abc"
问题是如何用更优雅高效的代码创建从String
到TestBase
及其子类的隐式转换?(也许只有一个隐式函数?)This is the Code I run in Scala REPL
您可以像这样将其重写为一个隐式定义。
implicit def conv[A <: TestBase](str: String): A = {println(str); null.asInstanceOf[A] }
但是根据您真正的尝试,可能有比将所有 Strings
转换为任何 TestBase
.[=18 更好的解决方案=]
编辑: 出于某种原因,Scala 在选择隐式转换时似乎没有考虑类型约束。它变得更加奇怪:
scala> implicit def bla2Test[A](str: String)(implicit ev: A <:< TestBase): A = null.asInstanceOf[A]
warning: there were 1 feature warning(s); re-run with -feature for details
bla2Test: [A](str: String)(implicit ev: <:<[A,TestBase])A
scala> val notTest: NotTest = "str"
notTest: NotTest = null
scala> implicitly[NotTest <:< TestBase]
<console>:15: error: Cannot prove that NotTest <:< TestBase.
implicitly[NotTest <:< TestBase]
^
因此编译器向 bla2Test
提供了一个 NotTest <:< TestBase
的实例,但不存在实例。
当你想检查类型时 A
:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> implicit def bla2Test[A <: TestBase](str: String)(implicit tag: TypeTag[A]): A = { println(tag); null.asInstanceOf[A] }
warning: there was one feature warning; re-run with -feature for details
bla2Test: [A <: TestBase](str: String)(implicit tag: reflect.runtime.universe.TypeTag[A])A
scala> val notTest: NotTest = "str"
<console>:21: error: type mismatch;
found : String("str")
required: NotTest
val notTest: NotTest = "str"
^
scala> val notTest: TestBase = "str"
<console>:20: error: macro has not been expanded
val notTest: TestBase = "str"
^