2011-04-19 36 views
9

我試圖檢測隱式轉換是否存在,並根據它執行一些代碼。例如:測試隱式轉換是否可用

if (x can-be-converted-to SomeType) 
    return something(conversion(x)) 
else 
    return someotherthing(x) 

例如,x是一個Int,應該轉換爲RichInt。 這可能在斯卡拉?如果是,如何?

感謝

+4

隱式轉換僅在編譯時和不存在的在運行時。如果你想測試這種轉換是否存在,你可以寫下代碼並嘗試編譯它。編譯器會告訴你它是否可以編譯。 – sschaef 2011-04-19 14:30:37

回答

11

正如其他人已經提到implicits在編譯時間,所以也許你應該寧願用類型類來解決這樣的問題解決了。這樣你就可以將功能擴展到其他類型。

您也可以只需要現有的隱含價值,但沒有直接表達的隱含價值不存在除了默認參數的方式。

Jean-Phiippe使用默認參數的解決方案已經相當不錯了,但如果您定義了一個可替代隱式參數的單例,則可以取消null。將它設爲私有是因爲它在其他代碼中實際上沒有用處,甚至可能是危險的,因爲隱式轉換可能會隱式發生。

private case object NoConversion extends (Any => Nothing) { 
    def apply(x: Any) = sys.error("No conversion") 
} 

// Just for convenience so NoConversion does not escape the scope. 
private def noConversion: Any => Nothing = NoConversion 

// and now some convenience methods that can be safely exposed: 

def canConvert[A,B]()(implicit f: A => B = noConversion) = 
    (f ne NoConversion) 

def tryConvert[A,B](a: A)(implicit f: A => B = noConversion): Either[A,B] = 
    if (f eq NoConversion) Left(a) else Right(f(a)) 

def optConvert[A,B](a: A)(implicit f: A => B = noConversion): Option[B] = 
    if (f ne NoConversion) Some(f(a)) else None 
+0

感謝您的回答。當使用「canConvert [布爾,有序[布爾]]」進行測試時,它返回false。我認爲將會使用轉換爲RichBoolean,但似乎沒有。哪裏不對? – 2011-04-21 07:44:04

+0

如果沒有代碼,我將不得不猜測:可能你用括號調用它:'canConvert [Boolean,Ordered [Boolean]]()'。編譯器然後填入默認參數 - 這不是你想要的。從調用中刪除括號或在隱式參數之前添加一個空參數列表。 – Moritz 2011-04-21 11:38:45

+0

@saucisson我更新了代碼以包含一個空的參數列表 - 現在如果您調用具有或不具有空參數列表的'canConvert'方法並不重要。 – Moritz 2011-04-21 12:02:13

9

你可以嘗試將它傳遞給需要相應的隱含參數與null默認的方法:

def toB[A](a: A)(implicit convertFct: A => B = null) = 
    if (convertFct != null) 
    convertFct(a) 
    else 
    someOtherThing(a) 

注意,它看起來好奇,我在運行時檢查這一點,因爲編譯器在編譯時知道這樣的轉換函數是否可用。