Question about Mixins and calling a method

C

Carlos Ortega

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

class TelescopeScheduler
include Observable

def initialize
@observer_list = [ ]
end

def add_viewer( viewer )
@observer_list << viewer
end
end

visor1 = "Carlos"
visor2 = "Ana"
my_telescope = TelescopeScheduler.new
my_telescope.add_viewer(visor1)
my_telescope.add_viewer(visor2)
my_telescope.print_observers

--------------------------
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

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 ?

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?

Any help with this questions would be very appreciated.
Best Regards
Carlos
 
T

Thomas B.

Carlos said:
1) Is it possible to invoke a method with a "<<" notation ?

It is not 'invoking a method with "<<" notation,' it is simply calling
the method named observers without any arguments, and then calling << on
the result of the method. This is equivalent to:
(@observer_list||=[])<<obj
or even:
(@observer_list||=[]).<<(obj)

Now: the method observers initialises the instance variable
@observer_list. The operator ||= assigns the empty array to the variable
if the variable is still nil at the moment of the call (so it will
assign the empty array only on the first call), and then return the
variable, no mater if the assignment was done or not. So the line
observers<<obj does the following:
@observer_list=[] if not @observer_list
@observer_list<<obj
On the other side while reviewing the "observers" method, I noticed that
there is no parameter in its definition:
Parentheses can be skipped both in definition and in call of a methods,
if there are no parameters.
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?

Again, this is a call to the method observers, and then a call to the
method each of the result you got. The method observers never returns
nil, because it either initialises or just returns the already
initialised @observer_list.

The instance variable @observer_list itself is not defined anywhere
though, because you don't have to declare instance variables in any way.
Simply if you try to read a variable for the first time, it returns nil
if the variable has not been assigned before.

You can read more about classes and their features here:
http://al2o3-cr.blogspot.com/2008/08/class-class.html

TPR.
 
R

Rick DeNatale

[Note: parts of this message were removed to make it a legal post.]

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Mixins 5
Dynamically mixins? 5
mixins 2
Python Mixins 9
improvements on mixins 6
mysterious behavior of mixins 4
skip_before_filter (Do I need a lesson in modules/mixins?) 12
Mixins and variables 1

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,144
Latest member
KetoBaseReviews
Top