Jim Freeze <jim / freeze.org> wrote:
> On 9/27/05, Jim Freeze <jim / freeze.org> wrote:
>
> Concerning multiple containers for an object:
>> Here are four methods that I can see as potential solutions:
>>
>>   1. obj.each(:container) { |element| ... }
>>   2. obj.each_container { |element| ... }
>>   3. obj.container.each { |element| ... }
>>   4. obj.container; obj.each { |element| ... }
>>
>> No. (4) simply sets an internal state variable to indicate which
>> container #each uses. Not pretty, and not thread safe, but permits
>> Enumerable to
>> be used.

4. is definitely a non option.  That's in the same league as containers 
glued together with an iterator (not #each).  That's simply a don't do. 
It's thread unsafe and error prone.  I strongly favor 3 with an optional 
variant of a read only proxy returned (using Enumerator for example).  2 is 
ok also and maybe 1, too.  Normally OO suggests to have separate methods but 
since you can easily say this in Ruby 1 seems ok, too:

def each(cont, &b)
  instance_variable_get("@#{cont}").each(&b)
  self
end

IOW you don't need to touch this method when you add more containers.

> I am curious what people think about these methods.
> To all you pattern experts, is there a pattern for this
> situation?

Not that I'm a pattern expert...  I'll throw in my 0.02EUR anyway:

 - My rule of thumb, if the object's main task is to be a container, give it 
an each method - this makes usage for clients convenient (example TreeNode, 
each will iterate child nodes).

 - If there are several containers contained :-) then make them accessible 
and let clients work with them.  You save yourself a lot of hassle and name 
collisions (KISS).

 - Remember: there's no way to protect the internals of an instance: if 
someone wants to screw up your instance he can always use send, 
instance_eval, instance_variable_get and *_set to access your innards.

Kind regards

    robert