Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Ruby module inclusion exclude the module's singleton class?

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

like image 396
horseyguy Avatar asked Oct 03 '10 04:10

horseyguy


People also ask

What is difference between include and extend in Ruby?

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.

Can a module inherit from a class Ruby?

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.

Can you instantiate a module in Ruby?

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.

What does prepend do in Ruby?

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.


1 Answers

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

like image 81
horseyguy Avatar answered Sep 28 '22 01:09

horseyguy