2010-10-06 107 views
3

我正在为Scala隐式转换问题苦苦挣扎。下面的代码片段说明我的问题:Scala隐式转换问题

import org.junit.{ Test, Before, After }; 

class ImplicitsTest { 

    implicit def toStringWrapper(str: String) = new StringWrapper(str); 

    @Test 
    def test(){ 
     val res1: Predicate = "str" startsWith "other"; 
    } 

} 

class StringWrapper(str: String){ 

    def startsWith(other: String): Predicate = null; 

} 

trait Predicate 

我如何可以强制字符串“STR”通过隐式转换toStringWrapper转换得到startsWith返回谓词,而不是布尔?

代码示例不能编译。我知道String已经有了一个startsWith方法,我只想使用另一个方法,并且我认为使用隐式转换可能是一种方法。

回答

12

斯卡拉谢天谢地不让你在没有注意到的情况下潜入替换方法 - 如果你在一个类上调用一个方法,并且该类有该方法,那就是你得到的方法调用。否则可能会导致各种混乱。

让您有两个其他选项: (1)重命名方法 (2)添加特定的方法来执行转换。

第二种方法的工作原理是这样的:您定义一个既有您想要的方法又有一个返回自身的唯一命名方法的类,并且可以选择从该类隐式转换回字符串,如果您希望能够使用像原来的字符串的定制项目(就好像它扩展字符串):

object ImplicitExample { 
    class CustomString(s: String) { 
    def original = s 
    def custom = this 
    def startsWith(other: String): Int = if (s.startsWith(other)) 1 else 0 
    } 
    implicit def string_to_custom(s: String) = new CustomString(s) 
    implicit def custom_to_string(c: CustomString) = c.original 

    def test = { 
    println("This".custom.startsWith("Thi")) 
    println("This".custom.length()) 
    } 
} 

scala> ImplicitExample.test 
1 
4 

scala> 
+0

@ rex-kerr,谢谢您的详细解答。 – 2010-10-07 06:54:18

+1

我喜欢为'this'提供别名以避免第二个临时对象的模式。 – retronym 2010-10-11 21:09:13

2

的隐式转换是Scala触发仅当接收器不包含被调用的方法,或者如果一个表达式具有类型不同于预期的类型。

由于上述String对象包含方法startsWith,因此不会触发隐式转换。不过,编译器会检查右侧表达式"str".startsWith("other");(即Boolean)的类型是否可以转换为Predicate。由于范围内没有这种隐式转换,因此会报告错误。

另请注意,隐式转换必须是明确的。例如,您可以尝试使用隐式转换来重写其他一些方法的Scala字符串行为。 Java String对象不是斯卡拉序列(Seq),这意味着它们不具有诸如sorted之类的方法,该方法返回序列的排序版本。如果你调用它的字符串:

scala> "string" sorted 
res1: String = ginrst 

这工作,因为在Predef对象定义的隐式转换被触发。请注意,提供您自己的隐式转换会导致错误:

scala> implicit def wrap(s: String) = new { def sorted = "Hi!" } 
wrap: (s: String)java.lang.Object{def sorted: java.lang.String} 

scala> "string" sorted 
<console>:7: error: type mismatch; 
found : java.lang.String 
required: ?{val sorted: ?} 
Note that implicit conversions are not applicable because they are ambiguous: 
... 
+0

感谢您的回答。 – 2010-10-07 06:54:38