2013-04-06 116 views
4

我試圖找出從Scala調用Java API的方法。基本上,有一個ContentValues對象有幾個方法,如getAsString,getAsLong,每個方法都有其自己的不同返回類型。在Scala中調用基於模板類型的方法

是否可以將ContentValues包裝在另一個對象中,以便我可以添加一個get[T]方法,該方法根據T調用正確的getAsXXX方法?

我想什麼(沒有工作,抱怨曖昧含蓄分辨率):

object SContentValuesConversions { 

    case class SContentGetter[ScalaType](val check: String => Boolean, val getter: String => ScalaType) { 
    def getTyped(key: String): Option[ScalaType] = { 
     if (!check(key)) None 
     else Some(getter(key)) 
    } 
    } 

    implicit def SIntContentValues(cv: ContentValues) = 
    SContentGetter((cv containsKey _), (cv getAsInteger _)) 

    implicit def SLongContentValues(cv: ContentValues) = 
    SContentGetter((cv containsKey _), (cv getAsLong _)) 

    implicit def SStringContentValues(cv: ContentValues) = 
    SContentGetter((cv containsKey _), (cv getAsString _)) 
} 

回答

6

您可以使用相同的技術特徵CanBuildFrom藏品。

我們首先創建一個Getter案例類

case class Getter[T](getter: (ContentValues, String) => T) { 

    def getOpt(contentValues: ContentValues, key: String): Option[T] = 
    if (contentValues containsKey key) Some(getter(contentValues, key)) 
    else None 
} 

這使我們能夠創建一個ContentValues包裝,有需要的方法。現在

implicit class ContentValuesWrapper(val c: ContentValues) extends AnyVal { 
    def getAsOpt[T](key: String)(implicit getter: Getter[T]) = 
    getter.getOpt(c, key) 
} 

,以調用getAsOpt方法上ContentValues我們需要正確的類型提供的Getterimplicit實例。

object Getter { 
    implicit val intGetter = Getter(_ getAsInteger _) 
    implicit val longGetter = Getter(_ getAsLong _) 
    implicit val stringGetter = Getter(_ getAsString _) 
} 

現在你可以在ContentValues實例使用getAsOpt方法。

// fake version of ContentValues 
val c = 
    new ContentValues { 
    val m = Map("a" -> "1", "b" -> "2", "c" -> "3") 

    def getAsInteger(k: String): Int = getAsString(k).toInt 
    def getAsLong(k: String): Long = getAsString(k).toLong 
    def getAsString(k: String): String = m(k) 

    def containsKey(k: String): Boolean = m contains k 
    } 

c.getAsOpt[Int]("a")  //Option[Int] = Some(1) 
c.getAsOpt[Long]("b")  //Option[Long] = Some(2) 
c.getAsOpt[String]("c") //Option[String] = Some(3) 
c.getAsOpt[Int]("d")  //Option[Int] = None 
c.getAsOpt[Long]("e")  //Option[Long] = None 
c.getAsOpt[String]("f") //Option[String] = None 
+0

非常感謝!我不確定爲什麼我的方式不起作用,但我會放棄它;) – 2013-04-06 11:22:44

+0

好吧,你有三個無法區分的含義,增加了一個'getTyped'方法。編譯器沒有足夠的信息來從類似'c.getTyped(「x」)' – EECOLOR 2013-04-06 11:25:57

+0

'的方法中選擇正確的信息啊,是的,所以參數化'getAsOpt'完成了這個技巧,並告訴編譯器足以區分這些轉換?有道理,我猜! – 2013-04-06 11:30:19