|
在設計程式的過程中,經常有的需求之一,就是希望逐一取得某物件內部的所有資料(或物件),像是取得ArrayList中所有的資料,或取得HashSet中所有的資料。 例如,您也許會希望設計一個foreach方法,可以將丟給它的物件中的資料逐一取得並顯示在主控台中: List<String> list = new ArrayList<String>(); ... foreach(list); Set<String> set = new HashSet<String>(); .... foreach(set); 因為List是有序結構並有索引特性,而Set則為無序不重複的特性,兩者所提供的公開存取方法也不相同,如何將foreach方法設計的通用是個問題。 無 論是List或Set,都有個iterator()方法可以傳回一個Iterator物件,這個物件會收集List或Set物件內部資料,並有 hasNext()、next()方法可以使用,而實際上,這個方法是繼承自Collection介面(List與Set的父介面),您可以這麼設計 foreach方法: public static void foreach(Collection<String> collection) { Iterator<String> iterator = collection.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); } } 現在,無論是List或Set,無論真正的實作是ArrayList、LinkedList、HashSet...,都可以使用這個foreach方法來顯示內部所收集的物件。 這 是Iterator模式的實現,不同的物件內部在組織資料方式並不相同(陣列?鏈結?雜湊?),所提供的公開存取介面也不一樣,為了有一致的方式來逐一取 得物件內部的資料,您可以讓一個Iterator於物件內部進行收集,之後傳回Iterator物件,透過該Iterator來逐一取得物件內部資料。 以Java 的Collection API設計來說,在JDK 1.4時,iterator()方法是定義在Collection介面上,每個Collection的實現類別,都會有iterator()方法,在 JDK5之後,則將iterator()方法定義在Iterable介面上,而Collection介面則繼承了Iterable介面: ![]() 由於物件在實作內部資料的組織時方式不盡相同,因此也只有物件本身才知道如何收集內部資料,因此Iterator的實作,通常會是物件的內部類別,外界無需關心,只要知道如何操作Iterator即可。 ![]() 由於Iterable介面在JDK5後引進,使得只要是實作Iterable介面的物件,皆可搭配foreach語法來使用。例如: import java.util.Iterator; 以上其實只是為了示範才又寫了一次foreach方法的實現,事實上,JDK5之後引入了foreach語法的支援,您可以直接這麼撰寫: for(Character c : new IterableString("Justin")) { System.out.println(c); } Python 在Iterator模式的實現方式,若要結合語法特性,則可透過類別上__iter__與__next__方法的定義。Python的foreach語法 會利用類別上的__iter__方法取得Iterator物件,而後利用所取得的Iterator物件之__next__方法來逐一取得資料,例如: class NumberGenerator: |