External iterator classes are verbose to use and to define. You need to define an iterator class for each collection class, and you need to update them in parallel. To use it, you need to instantiate the iterator and make method calls to iterate, fetch and see if there are more.
In 99% of use cases, all you want to do is run a block of code against each element.
A fourth option, which is in the general case superior to all three of your options, is the internal iterator. It delegates management of the iteration to the collection, rather than adding repetitive boilerplate to your functional code.
An internal iterator is an instance method of a collection which is passed a function which it calls for each element in the collection.
An example of internal iterators is seen in Ruby's core collection classes.
For the technically-minded, let me demonstrate the difference between the two with code (Ruby, because it's shorter). (Download the code from http://dave.burt.id.au/ruby/pair.rb to see it indented properly.)
attr_accessor :first, :last
def initialize(first = nil, last = nil)
@first = first
@last = last
# The internal iterator is an instance method
# The external iterator is a full-blown, separate class
# which also wants an instance method to obtain an
# iterator instance
# Wow, this iterator's definition is longer than the
@pair = pair
@next = :first
@next = :last
@next = nil
col = Pair.new "a", "b"
# Internal iterator: just pass the block to the iterator
col.each do |x|
# External iterator: instantiate, check, fetch
iter = col.iterator
x = iter.next