2012-09-03 101 views
3

我有下面的類定義調用底層對象。舉例來說,我希望能夠做到:轉發在斯卡拉

val a = new Foo({() => List(1, 2, 3).toIterator }) 
val b = new Foo({() => List(4, 5, 6).toIterator }) 
val c = a ++ b 

而且具有c等於:

new Foo({() => a.values ++ b.values }) 

我看了一下代理(IterableForwarderTraversableForwarder,...),但沒有似乎很適合將方法轉發到Iterator,我仍然希望將Foo同時保留爲靜態和動態結果類型。

實現此行爲的最佳方式是什麼,而不定義每種轉發方法?

+0

看看迭代器特徵的定義,只有hasNext和next方法都是抽象的,所以你可以很容易地提供給他們。更重要的一點是Iterator可以擴展TraversableOnce,因此可以通過它的值進行單次傳遞,這限制了代理或派生表單的使用。問問自己,使用迭代器是否會更好。 –

+0

我需要'Foo'類,因爲我需要能夠通過它的值進行多次傳遞,而不僅僅是作爲'Iterator'。 –

回答

1

我需要Foo類,因爲它不僅僅作爲一個迭代器,因爲我需要能夠通過其多個值進行多次傳遞。

然後你想要一個TraverableIterable。要讓它們按你的意願工作,你需要擴展它們,並且TraversableLikeIterableLike,通過它們你可以指定返回類型。您還需要同時提供BuilderCanBuildFrom

這裏有一個簡單的實現:

import scala.collection.IterableLike 
import scala.collection.mutable.LazyBuilder 
class Foo[T](iteratorThunk:() => Iterator[T]) extends Iterable[T] with IterableLike[T, Foo[T]] { 
    def iterator = iteratorThunk() 
    override protected def newBuilder = new Foo.FooBuilder[T] 
} 

object Foo { 
    class FooBuilder[T] extends LazyBuilder[T, Foo[T]] { 
    def result(): Foo[T] = { 
     val coll = parts.toList.flatten 
     new Foo(() => coll.iterator) 
    } 
    } 
} 
+0

謝謝。我已經用適當的CanBuildFrom補充了你的實現,並按照我的意願進行了工作。 –

+0

您是否認爲可以避免'parts.toList.flatten'部分,以便添加到構建器的迭代器不會在那裏被評估? –

+0

@JoaoAzevedo你希望'iteratorThunk'每次都返回相同的元素,對嗎?由於'Iterator'只能遍歷一次,所以你必須在某個地方「保存」它。例如,這就是迭代器的「dup」。鑑於此,你可以將它保存在建造者身上。 –