2016-03-01 47 views
1

下面的代码,斯卡拉隐式转换(字符串到一个自定义的类和它的子类)

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" 

的问题是如何从StringTestBase隐式转换和它的子类具有更加优雅和高效代码?(也许只是一个隐含的函数?)This is the Code I run in Scala REPL

+0

另外,**类NotTest(STR:字符串)**; ** val notTest:NotTest =“abc”**不应通过编译,因为NotTest不是TestBase的子类。 – Hario

回答

1

你可以重写这一个像这样的隐式高清。

implicit def conv[A <: TestBase](str: String): A = {println(str); null.asInstanceOf[A] } 

但是这取决于你是什么真正努力,有可能比将所有Strings任何TestBase一个更好的解决方案。


编辑: 出于某种原因,斯卡拉似乎没有选择隐式转换时要考虑的类型约束。它会变得怪异:

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] 
         ^

所以编译器提供的NotTest <:< TestBase一个实例bla2Test但没有实例存在。

而当你想检查类型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" 
          ^
+0

假设我有一个**类NotTest(str:String)** val notTest:NotTest =“abc”;这一个也隐式地将字符串转移到NotTest,这不是我想要的。 – Hario

+0

@Francis,如何创建一个扩展TestBase的新子属性。然后,所有想要隐式隐藏的类都可以直接扩展该特性而不是TestBase,并且可以使用Jasper-M的解决方案。 – dhg

+0

如果'NotTest'不是'TestBase'的子类,那么'val notTest:NotTest =“abc”'不会使用我提供的解决方案进行编译。 –