2011-08-02 68 views
6

把这个代码:Scala的隐式转换范围发出

class Register(var value:Int = 0) { 
     def getZeroFlag() : Boolean = (value & 0x80) != 0 
    } 

    object Register { 
     implicit def reg2int(r:Register):Int = r.value 
     implicit def bool2int(b:Boolean):Int = if (b) 1 else 0 
    } 

我想使用它,像这样:

val x = register.getZeroFlag + 10 

,但我与打招呼:

type mismatch; found : Boolean required: Int 

什么去?我是否需要定义一个隐式函数来返回一个布尔值?

回答

14

下面是一个例子演示了如何使用您的implicits:

这里
object Test { 
    val register = new Register(42) 
    val x = 1 + register // implicitly calling reg2int from companion object 
    val y = register - 1 // same 
    // val z = register + 1 // doesn't work because "+" means string concatenation 

    // need to bring bool2int implicit into scope before it can be used 
    import Register._ 
    val w = register.getZeroFlag() + 2 // this works now 
    val z2 = register + 1 // works because in-scope implicits have higher priority 
} 

两个潜在的非显而易见的事情:

  • 在寻求隐式转换,或从类型Register,编译器的目标将看伴侣对象Register。这就是为什么我们不需要明确将reg2int纳入定义xy的范围。但是,转换bool2int确实需要在范围内,因为它未在BooleanInt随播对象中定义。
  • 已在所有对象上定义方法+,以表示通过scala.Predef中的隐含any2stringadd来表示字符串连接。定义val z是非法的,因为隐式字符串连接的优先级高于reg2int(伴随对象中的隐含优先级相对较低)。然而,定义val z2的作用是因为我们已经将reg2int纳入了范围,给予它更高的优先级。

有关implicits编译器的搜索怎么样,看到丹尼尔索布拉尔的非常好的解释更多的细节:Where does Scala look for implicits?

+0

神奇。这很好地解释了范围界定。 –

+0

我刚才发现,对象上的._对于导入Object中定义的东西是必要的。认为这将是“隐含的”(双关意图) – drame