2010-10-06 145 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