From: Rick DeNatale Date: 2008-09-21T03:23:01+09:00 Subject: Re: Question about Mixins and calling a method ------=_Part_57465_28066223.1221935452603 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline On Sat, Sep 20, 2008 at 1:10 PM, Carlos Ortega wrote: > Hi folks. > I tried to reproduce a Mixin example that is include in the Pick Axe > book, here's the code: > > module Observable > def observers > @observer_list ||= [] > end > > def add_observer( obj ) > # ----????? > observers << obj > end > > def print_observers > @observer_list.each{ |i| puts i } > end > > end > > def notify_observers > # ----????? > observers.each {|o| o.update } > end > > It works great however while reviewing the code I noticed a couple of > situations that I really don't understand: > 1) Is it possible to invoke a method with a "<<" notation ? > > What I mean is that inside the "add_observer" method I'm calling > observers using << instead of parenthesis: > > def add_observer( obj ) > observers << obj > end observers is a method defined in the Observable module. I'll address << after... On the other side while reviewing the "observers" method, I noticed that > there is no parameter in its definition: > def observers > @observer_list ||= [] > end > Is this valid ? ( I suppose it is because it works ), but how does this > works ? Sure it is valid there's no rule that a method must take a parameter, lots don't. So what is happening in the add_observer method is that the observers method is invoked, it uses a lazy initialization pattern to initialize and instance variable to an empty array if necessary, and returns that instance variable. Note that this is interpreted the same as if it had been: def add_observer(obj) self.observers << obj end the self is implied. Then the << message is sent to the result of the observers method with obj as the parameter. > > > 2) Same situation happens in the "notify_observers" method, in it I can > invoke "observers.each" although it is not defined anywhere. Why can I > do that? Same thing each is being sent to the object resulting from the observers method. Now lets look at your usage of the module: > class TelescopeScheduler > include Observable > def initialize > @observer_list = [ ] > end This is unnecessary, since @observer_list is initialized by the module method when needed. > def add_viewer( viewer ) > @observer_list << viewer > end This isn't really using the module. The whole TelescopeScheduler class, as written, can be just: class TelescopeScheduler include Observable alias_method :add_viewer, :add_observer end -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/ ------=_Part_57465_28066223.1221935452603--