I'm in the middle of Why's Poignent guide, and this one has me
stumped. Let's say MyClass exists. I want to add to it. So far, all
the examples have done:
class MyClass
def new_method
...
end
end
Now he adds:
class << MyClass
def new_method
...
end
end
He states the difference is the << operator allows you to alter the
definition of an object. Isn't that what I'm doing in the first
example as well? Won't my new_method be added to the class regardless?
He also states:
When you see class << obj, believe in your heart, I'm adding directly
to the definition of obj.
I'm failing to see what the practical difference is...
So you're essentially added a protected method? Would that be correct?
(or is it private?) So the method could only be used by other methods
withing the class?
The << indicates you're adding class level methods rather than instance level.>
But with the << operator, you can't call it on an instance.
So you're essentially added a protected method? Would that be correct?
(or is it private?) So the method could only be used by other methods
withing the class?
Doing this:
class << obj
...
end
opens up a class definition block for the "singleton class" of obj.
Inside that singleton class, the methods you define are available only
to obj. They're not private methods (which would also be available to
other objects of the same class as obj). They're *singleton* methods,
which exist only to be called by that one specific object.
When obj is a class, as in class << SomeClass, the singleton methods
pertain to the class object, and are also called "class methods".
(They are also special-cased in one or two ways; but for the most
part, giving singleton methods to class objects is just one variant of
the general practice of giving singleton methods to objects.)
Right. Just to tie it back to _why's book, this is where the original
explanation's mention of "changing the object's definition" comes in.
When you define a class, you're creating a Class instance, and when
you use <<, you're changing the definition of that Class instance
(i.e., changing that object's definition).
It's confusing, I know, but if you read David's link and play with it
in irb, it'll sink in.
So, the following ought to work? Cuz the modules are loaded but
ArInstance.find does not invoke the logger.
Thx
module ArSugar
def self.included(base)
RAILS_DEFAULT_LOGGER.debug "running included code"
base.class_eval do
base.extend(ClassMethods)
class << self
alias_method(:old_find, :find) unless method_defined?
(:old_find)
end
end
end
module ClassMethods
RAILS_DEFAULT_LOGGER.debug "class methods"
def find(*args)
RAILS_DEFAULT_LOGGER.debug "my finder"
old_find(args)
end
end
end