作者 内容
 qliang1   HELP: Iterator能写成通用的吗?
 


Iterator为了重用,不惜写成模板类,以便不知道自己遍历的是什么东西。可如果构造他(iterator)的参数不是个数组,他还是要知道如何获取遍历目标的第一个或下一个,看来知道还是不可避免。

GO4的书里举的例子一下子就用STL的List初始化ListIterator,后来ListIterator的First/Next/Current自然好写得一塌糊涂,因为作者认为大家都该知道STL List有个Get(int current_index)方法(//我咋就不知道呢:))。

有趣的地方就在这儿。好像STL怎么包装数组或链表的细节就没人管了。而写这个ListIterator本身就是在处理细节。

简单地说,我的问题是:Iterator不可避免地要知道自己所遍历的element的一些细节(请注意,是方法名,很严重了),是不是?如果是这样,通用性何在?

//note:请别用纯数组举例了,哪怕用个链表你也会体会问题的必要性。

谢谢!

 03/10/09 14:24 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  如果能,还要迭代器干什么?:-)
 

有点想象力,呵呵。

iterator不需要知道element的细节,它需要知道的是container的细节:-)

 03/10/09 18:32 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 frankwoo  回复: HELP: Iterator能写成通用的吗?
 

smilemac已经说了。
找个STL的代码看看
就明白了。

 03/10/09 21:56 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 qliang1   回复: 如果能,还要迭代器干什么?:-)
 

那container要知道element的细节喽?

 03/10/10 04:27 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 sealw  通用性在于,使用Iterator的代码不需要知道容器的内部组织结构
 

写成模板类不是为了让Iterator不知道自己遍历的是什么,而是为了类型安全以及少写一些强制类型转换代码

您可以在开始设计时写出
Iterator it = vector.iterator();
然后在以后的设计中将其改为
Iterator it = veryComplexContainer.iterator();
然后客户部分代码都不需要改动。甚至这部分的代码改动也可以隔离掉,写成
Iterator it = objectFactory.getCandyIterator();

所有的变化都集中在了objectFactory的实现中,而在那个实现里,内部是高内聚的。但对于外部的客户代码,则是低耦合的。

Iterator本身一定知道自己要遍历的容器的组织结构,而向容器的使用者提供了一个低耦合的Iterator接口,从而将变化局限在了局部代码之中。

 03/10/10 09:00 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  不需要。
 
 03/10/10 09:29 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 qliang1   如果元素本身是有结构的呢?比如链表,二叉树,不知道其细节能构造Container/Iterator吗?
 

如果元素是数组,那是不需要知道的,只要知道类型名就可以。类模板就搞定了。

可我们不能勒令客户采用一种简单结构或始终用STL或Java里的Vector等把结构弄得已经很完美。Suppose他们就是像我一样的Rookie,自己写了个符合工程要求的数据结构,现在又在想不改动它的前提下用一个外边的Iterator遍历它。

我觉得知道它的细节是不可避免的。

 03/10/10 09:51 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  可以。
 

容器本身是不需要了解元素是什么的,哪怕这个元素是另外一个容器。

 03/10/10 09:55 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 qliang1   老大是在解释工厂模式的好处了
 

Iterator是可以被Factory一把,但这里说的是Iterator能否被独立出来的问题啊。要是Iterator必须知道Container的细节,那么下次遍历别的Container时,岂不要重写?

老大的意思我心领。假想只有一个具体的Iterator,比如Preorder,能独立地被写出来吗?(这里我们姑且不管以后还写什么别的Iterator的问题,也就无工厂模式的考虑了)

 03/10/10 10:07 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 qliang1   我只给个二叉树的根给你构造PreorderIterator,不告诉你得到左孩子的方法名叫left(),你写得出这个遍历器的Next()方法吗?
 

???

 03/10/10 10:11 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  回复: 我只给个二叉树的根给你构造PreorderIterator,不告诉你得到左孩子的方法名叫left(),你写得出这个遍历器的Next()方法吗?
 

我前面已经告诉你了,iterator必须知道container的细节,不存在独立于container的iterator,或者说,一个iterator必须依存某个container存在,统一的是iteraor的接口,不是实现。

 03/10/10 10:17 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 qliang1   那就是说,具体的Iterator(比如二叉树Preorder)想能被复用,只要保证Container提供一致的构造该Iterator所需的方法就可以了?
 

看来还是能通用的,就是要求container规整一点,最好满足一个方法接口。

 03/10/10 10:37 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  Iterator就是這個接口,如果container另外有這樣通用接口,就不需要iterator這個接口了。
 

你沒看懂我第一個回復的意思嗎?

 03/10/10 10:43 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 sealw  不能。container如何组织element的细节必须有某个类知道,通常就是由container的iterator方法返回一个类来知道这方面的信息,这个类实现iterator接口。
 

您可能对Iterator的设计意图不很了解。

 03/10/10 18:18 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首