2011-03-30 15 views
3

比方說,我有一個名爲LongArrayWritable的類型,它是一個Long Array數組的裝箱表示。我有這些類型之間的轉換隱含的定義:斯卡拉的含義是否可以轉換更高級的類型?

implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/} 
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/} 

現在,我也有,在他們的一般形式java.lang.Iterable和scala.collection.List [X]之間的轉換implicits:

implicit def iterator2list[X](it : java.lang.Iterable[X]) : List[X] { /* elided */ } 
implicit def list2iterator[X](list : List[X]) : java.lang.Iterable[X] { /* elided */ } 

有了這些定義,scala編譯器是否可以推斷java.lang.Iterable [LongArrayWritable]和List [Array [Long]](相當於iterator2list(iterator).map(unboxLongArray(_)))之間的隱式轉換,或者這超出了implicits的功能,因此需要它是自己的(顯式的?)隱式定義?

感謝,

+0

只是一個文體評論;我傾向於迴避這種隱式轉換,因爲我認爲它們妨礙了可讀性並掩蓋了潛在的昂貴操作。我相信這是一個更好的風格的例子可以在這裏找到:http://www.scala-lang.org/api/current/scala/collection/JavaConverters$.html(比較同一包中的JavaConversions) – 2011-03-30 20:28:42

+0

也,我不確定更高級的類型與這個問題有什麼關係;您不是在此代碼中的任何位置抽象出類型構造函數。 – 2011-03-30 20:30:12

+0

啊 - 兩個好點。我可以理解implicits是如何掩蓋轉換操作的代價 - 我一直試圖從我的代碼中刪除所有明確的轉換,這可能不是一個特別好的設計決定。對於更高級的類型,我想我可能在這裏略微混淆了我的術語 - 我可能會將高級類型與參數化類型混淆。事實上,我並不完全清楚這個區別,但這可能完全是一個單獨的問題! :-) – mistertim 2011-03-31 08:14:12

回答

7

有覆蓋這個問題後:How can I chain implicits in Scala?。實質上,您需要有一個視圖才能轉換爲LongArrayWritable。這意味着,轉換爲LongArrayWritable隱含def接收的隱式參數(結合稱爲視圖),以使一個參數這個def是不直接的Array但某種類型的可轉換爲Array

object LongArrayWritable { 
    implicit def fromArraySource[A <% Array[Long]](a: A): LongArrayWritable = apply(a) 
} 
case class LongArrayWritable(a: Array[Long]) 

def test(a: LongArrayWritable): Unit = println("OK") 

現在這適用於陣列:

test(Array(1L, 2L, 3L)) 
然而

,因爲Array不是Iterable並沒有默認的轉換從IterableArray範圍,你需要添加一個:

implicit def iterable2Array[A: ClassManifest](i: Iterable[A]): Array[A] = i.toArray 

那麼它的工作原理:

test(List(1L, 2L, 3L)) 

的觀點勢必A <% Array[Long]A => Array[Long]類型的隱含參數的快捷方式,所以你可能也寫

implicit def fromArraySource[A](a: A)(implicit view: A => Array[Long]) ... 
+0

謝謝,對於延遲迴復感到抱歉。現在這一切非常清楚! – mistertim 2011-04-11 11:07:53