When classes are inherited in Ruby the singleton classes are also inherited:
class A
def self.hello
puts "hello"
end
end
class B < A
end
B.hello #=> "hello"
Yet with modules, this is not the case:
module M
def self.goodbye
puts "goodbye"
end
end
class A
include M
end
A.goodbye #=> NameError
To get around this limitation many ppl resort to this ugly hack:
module M
def self.included(c)
c.extend ClassMethods
end
module ClassMethods
def goodbye
puts "goodbye"
end
end
end
Ok, so my question: is there a theoretical/conceptual reason behind this limitation on modules? or was it just an implementation difficulty?
After looking at the C source code (YARV/MRI) I can identify there is an implementation difficulty (not insurmountable, but one all the same), but is this the sole reason? Are there any other reasons for this limitation?
thanks
In simple words, the difference between include and extend is that 'include' is for adding methods only to an instance of a class and 'extend' is for adding methods to the class but not to its instance.
The Ruby class Class inherits from Module and adds things like instantiation, properties, etc – all things you would normally think a class would have. Because Module is literally an ancestor of Class , this means Modules can be treated like classes in some ways. As mentioned, you can find Module in the array Class.
You can define and access instance variables within a module's instance methods, but you can't actually instantiate a module. A module's instance variables exist only within objects of a class that includes the module.
With prepend, the module is added before the class in the ancestor chain. This means ruby will look at the module to see if an instance method is defined before checking if it is defined in the class. This is useful if you want to wrap some logic around your methods.
Unless anyone can come up with a compelling argument, i feel that the limitation is just down to implementation difficulty. Nonetheless i've been working on the problem the last couple of days and have (in beta) a new version of include called include_complete
that gets around these difficulties and allows modules inheritance to work like class inheritance (bringing in the singleton)
Check out the project here: http://github.com/banister/include_complete
And beware the project is still very much in beta, but still seems to work as desired so far
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With