module_function for Ruby Class - ruby

As I understand ruby classes, they are almost the same as modules except with an added functionality of being able to instantiate it. As Class inherits from Module, I assumed that then every class (objects of class Class) would have access to module_function, but it does not seem to be the case. When I did a difference of Module and Class' private_instance_methods, I found that Module has 3 methods more than Class - [:append_features, :extend_object, :module_function]
How were these functions removed from the call chain for Class objects and more importantly why?

Those core features are implemented in C, so discussing about that does not have generality, and is not useful. Within Ruby, you can undefine an inherited method without undefining the method in the superclass by using undef.
class Foo
def foo; end
end
class Bar < Foo
undef :foo
end
Foo.new.foo
# => nil
Bar.new.foo
# => NoMethodError: undefined method `foo' for #<Bar:0x007f85c3ce3330>
append_features is a hook to be called right before a module is include-d, which a module can be, but not a class.
extend_object is a hook to be called right before a module is extend-ed, which a module can be, but not a class.
The purpose of module_function is to double the method as a class method and a private instance method, latter of which is useful when you include that module, which can be done with a module but not with a class.

Related

How and why is the super class of singleton_class of BasicObject is Class class in Ruby?

By definition, a singleton class of an object also inherits the singleton class of the superclass of the object. The BasicObject in ruby doesn't have any superclass as it is the most basic level class
>> BasicObject.superclass
=> nil
But when the same method called on its singleton class, it results:
>> BasicObject.singleton_class.superclass
=> Class
and also why no other object in ruby have the Class class as its superclass?
How the logic behind the superclass of singleton_class of BasicObject is implemented in Ruby?
In general, the superclass of the singleton class of an object is the class of the object. I.e. for any object foo with a singleton class, the following holds:
foo.singleton_class.superclass == foo.class
However, for classes, this would be somewhat boring: the class of every class is Class, so the superclass of every class's singleton class would always be Class.
That is not particularly useful, since it would break some reasonable assumptions. For example, if I have something like this:
class Super
def self.super_singleton_method; end
end
class Sub < Super; end
I would expect to be able to call Sub.super_singleton_method. However, in order to do this, Super.singleton_class needs to be somewhere in the method lookup chain of Sub.singleton_class.
So, for classes, the rule is somewhat different: the superclass of the singleton class of a class is the singleton class of the superclass of the class. I.e. for any class Foo, the following holds:
Foo.singleton_class.superclass == Foo.superclass.singleton_class
If you want, you can check whether this is true for every class in your system:
ObjectSpace.each_object(Class).select do |klass|
klass.singleton_class.superclass != klass.superclass.singleton_class
end
#=> [BasicObject]
So, as you can see, this property does hold for all classes except BasicObject.
The simple answer for why BasicObject is different is that BasicObject has no superclass, and thus we cannot apply the rule. So, we fall back on the more general rule for all objects that
foo.singleton_class.superclass == foo.class
And BasicObject's class is Class, therefore,
BasicObject.singleton_class.superclass == BasicObject.class
BasicObject.singleton_class.superclass == Class
and also why no other object in ruby have the Class class as its superclass?
The only reason to inherit from Class would be to override the behavior of how inheritance or method lookup works in Ruby. But Ruby does not allow to override this. How inheritance and method lookup works is part of the language specification and cannot be changed. Therefore, inheriting from Class is illegal:
class MyClass < Class; end
# can't make subclass of Class (TypeError)
Thus there cannot be any object which has Class as its superclass, except singleton classes of classes. (Ruby can of course break its own rules since it is the one that makes the rules.)
How the logic behind the superclass of singleton_class of BasicObject is implemented in Ruby?
It isn't. You cannot explain how this works in Ruby, since it is part of the definition of Ruby itself.
It is similar to how Class is a subclass of Module, but Module is a class, i.e. an instance of Class. You cannot explain this from within Ruby using the rules of Ruby, but the Ruby implementation can, of course, set things up so that this works, since the Ruby implementation itself does not have to abide by the rules of Ruby: it is the one enforcing the rules, so it can just choose not to enforce them for itself.
By definition, a singleton class of an object also inherits the singleton class of the superclass of the object.
Instead of taking this for granted, let's figure out why it was implemented this way.
In Ruby, there are instance methods and class methods. The class methods however are in fact instance methods of the singleton class:
class MyClass
def foo
end
def self.bar
end
end
MyClass.instance_methods(false)
#=> [:foo]
MyClass.singleton_class.instance_methods(false)
#=> [:bar]
As a diagram:
MyClass ---> #<Class:MyClass>
foo bar
Now, if you create a subclass MySubClass, it inherits both, the instance methods and the class methods from its superclass MyClass:
class MySubClass < MyClass
end
MySubClass.instance_methods
#=> [:foo, ...]
MySubClass.singleton_class.instance_methods
#=> [:bar, ...]
To get this working, the inheritance has to be established for both, the classes and the singleton classes:
MyClass ---> #<Class:MyClass>
foo bar
^ ^
| |
MySubClass ---> #<Class:MySubClass>
Ruby optimized this internally – the singleton classes are only created when needed. But conceptually, this is what happens.
Apart from that, MyClass and MySubClass already come with some built-in class methods, most notably .new which is used to create instances, but also .superclass.
You might know that the default implementation of .new calls .allocate under the hood. So somewhere there must be a sort of "root class" which contains these methods. And since they are class methods, it must sit on top of the singleton class side:
<singleton root class>
new
allocate
superclass
^
|
...
|
MyClass ---> #<Class:MyClass>
foo bar
^ ^
| |
MySubClass ---> #<Class:MySubClass>
And this mysterious top level singleton root class that provides the fundamental class methods for all other classes is ... Class!
Class.instance_methods(false)
#=> [:allocate, :superclass, :subclasses, :new]

Why can some classes and/or methods be called without instances of their parent class?

I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
#hours = 1
#minutes = 30
end
def showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object class and hence seem to be globally available. Why? From any context Object is always in the class hierarchy of self and hence private methods on Object are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name) as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended into class scope or included into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include or extend.
How can [Time.now] be called in this fashion? Shouldn't there be an
instance of Time first created?
The Time.now method is a class method, not an instance method and therefore can be called directly on the Time class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it
relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define
any method on the "global" level I can access it without referencing
the global object
You defined the showTime method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self and the subsequent call to mymethod is actually self.mymethod so it will work.
Time.now is a class method.
To define a class method, you need to define the method with self. : def self.method_name
class Clock
#hours = 1
#minutes = 30
def self.showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
Clock.showTime
#=> The time is: 1:30
If you want to call now on its own, you can do so inside Time class :
class Time
puts now
#=> 2017-01-19 22:17:29 +0100
end

What happens internally when a module is extended in Ruby?

Foo = Module.new
class MyClass
include Foo
end
When a module is included in a class, an anonymous proxy class is created and set as MyClass's superclass.
MyClass.ancestors => [MyClass, Foo, ...]
But what happens internally when a module is extended? How does Ruby handle this?
I think what you ask is Object#extend
So with extend, I can include any module's methods into that object.
For example I have a module called HelperModule:
module HelperModule
def foo
puts "from module helper"
end
end
Usage Example 1:
obj = Object.new
obj.extend HelperModule
obj.foo # => "from module helper"
Usage Example 2:
class MyClass
extend HelperModule
end
MyClass.foo # => "from module helper"
Internally, according to Metaprogramming Ruby:
Object#extend() is simply a shortcut that includes a module in the receiver’s eigenclass.
A brief explanation of ruby's methods call :
find the object's class, see if the method defined there
find that class's superclass, see if the method defined there
obj
|
| class
| superclass superclass
---> ObjectClass --------------> SuperClass1 --------------> SuperClass2 ....
The detailed explanation about eigenclass and method call path, please reference this awesome book Metaprogramming Ruby
Thanks
Whats happens internally when a module in extended in Ruby?
When a module M is included in a class C, an anonymous proxy class ⟦M′⟧ (called an include class) is created such that its method table pointer points to M's method table. (Same for the constant table and module variables.) ⟦M′⟧'s superclass is set to C's superclass and C's superclass is set to ⟦M′⟧.
Also, if M includes other modules, the process is applied recursively.
Actually, that's just the default behavior. What really happens is that include calls M.append_features(C), and you can customize all of that behavior by overriding that method.
I find the source code of Module#append_features in Rubinius quite readable.
obj.extend SomeModule is the same as obj.eigenclass.include SomeModule (Note: this is just pseudocode, but you will get the idea...).
In a nutshell, Ruby's include method will emulate inheritance: it will allow the including class access to the included module's instance methods, variables and constants as if they had been defined in the including class itself. Ruby does this by creating an anonymous proxy class (known as an eigenclass or singleton class), as you mentioned, which references the included module, and inserting it into the ancestors of the including class as the immediate superclass. This is what is known as a mixin in Ruby.
Using extend, however, interacts with the singleton class a little bit more:
module Foo
def baz
'baz'
end
end
module Blah
def blah
'blah'
end
end
class Bar
extend Foo
include Blah
def self.magic
'magic'
end
end
Extending Foo in Bar is identical (right down to its implementation in C) to saying
Bar.singleton_class.send( :include, Foo )
This means that it is the singleton class of Bar in which the methods and constants of Foo are essentially embedded, and thus class Bar, being an instance of its singleton class, will inherit this new functionality as so-called 'class' methods. In Ruby, modules and classes can only have instance methods, and thus the creation of a 'class' method will actually just create an instance method in the class's singleton class, to be inherited in this manner.
Bar.baz
# => 'baz'
Bar.magic
# => 'magic'
Bar.blah
# => NoMethodError
Bar.new.baz
# => NoMethodError
Bar.new.magic
# => NoMethodError
Bar.new.blah
# => 'blah'
Here you can see the differences in behavior of include and extend. To verify their behavior with regards to class ancestry, you can ask for the ancestors of Bar and its singleton class, and it will show you that module Blah is the immediate parent of Bar, but module Foo is the immediate parent of the singleton class.
Bar.ancestors
# => [Bar, Blah, Object, Kernel, BasicObject]
Bar.singleton_class.ancestors
# => [Foo, Class, Module, Object, Kernel, BasicObject]
From these results, you can see how inclusion emulates inheritance in the including class, and how extension is merely inclusion within the singleton class.
You might try looking at the answers I got for this question awhile back; they did an excellent job of explaining the behavior of the include and extend functionality.
This article has also helped me understand their differences.

Why doesn't Ruby module inheritance work like class inheritance?

Suppose I have a module called Flight with both class and instance methods. I can get its methods into a class using include, extend, or both:
class Bat < Mammal
# Add Flight's class methods to Bat.
extend Flight
# Add Flight's instance methods to Bat.
include Flight
...
end
include will add Flight to Bat.ancestors, but extend will not.
My question is, why is this different for modules than for classes? When I subclass Mammal, I always get both class and instance methods at once. However, when I mix in a module, I cannot get both class and instance methods at once (unless I use the self.included hook or something like ActiveSupport::Concern).
Is there a language-design issue behind this difference?
Both Module#include and Object#extend are used to add the instance methods of a Module to an Object.
Given the module:
module Flight
def can_fly?
true
end
end
Module#include is used to add (or mix in) the instance methods of a module to the instance methods of a class or a module:
class Bat < Mammal
include Flight
end
a = Bat.new()
a.can_fly? # true
It actually affects the Object#is_a? method, so:
a.is_a? Flight # true
Module#include is a private method, so it can only be called with function notation when defining a class or another module:
class Bat < Mammal
self.include Flight # NoMethodError: private method called
end
Object#extend adds the instance methods of a module as singleton methods to the object on which it's called, so you can do this:
b = Mammal.new()
b.extend Flight
b.can_fly? # true
b.is_a? Flight # true
c = Mammal.new()
c.can_fly? # NoMethodError: undefined method
And only b will have the instance methods from Flight; other Mammal objects won't.
When calling Object#extend inside a class definition, the methods are added to the eigenclass of the class you're defining.
This is the important difference between the two methods when using them inside a class definition, because the methods are added as class methods:
class Bat < Mammal
extend Flight
end
Bat.can_fly? # true
d = Bat.new
d.can_fly? # NoMethodError: undefined method
I would like to address one part of your question:
include will add Flight to Bat.ancestors, but extend will not.
extend is not the same as include so it does something different obviously... You can think of extend being equal to an include on the class' metaclass.
Have a look at the following example:
module M
end
class A
include M
end
# then you will see M within A's ancestors as you know
A.ancestors # => [A, M, Object...]
class B
# the following is roughly the same as extend M:
class <<self
include M
end
end
# then you will see M within B's metaclass' ancestors
MetaclassOfB = class <<B; self; end
MetaclassOfB.ancestors # => [M, Class, Module...]
So, since extend is like an include on the metaclass, you see the extended modules showing up in the metaclass' ancestor chain...
"When I subclass Mammal, I always get both class and instance methods at once"
That's because Bat class as an object also inherited the instance methods from Mammal singleton class.
Including a module into a class changes the method look up chain. So actually the class doesn't inherit any instance methods.
Extending a class with a module is same as extending any object. The class simply acquires the module's instance methods as class instance methods (ie. methods on the class object itself).

Ruby module_function, invoking module's private method, invoked in class method style on module shows error

test_module.rb
module MyModule
def module_func_a
puts "module_func_a invoked"
private_b
end
module_function :module_func_a
private
def private_b
puts "private_b invoked"
end
end
class MyClass
include MyModule
def test_module
module_func_a
end
end
Invoking module function from class
c = MyClass.new
c.test_module
Output 1:
$ ruby test_module.rb
module_func_a invoked
private_b invoked
Invoking module function on module in class method style
ma = MyModule.module_func_a
Output 2:
module_func_a invoked
test_module.rb:5:in `module_func_a': undefined local variable or method `private_b' for MyModule:Module (NameError)
from test_module.rb:31
As can be seen from the Output 1 and Output 2 when including the module in a class, no issue occurs when a module's private method gets invoked from a module function
while in case when directly invoking the module function on the module in class method style the module's private method, invoked from module function, is not found.
Can anybody make me understand the reason behind above behavior and whether invoking module function (which in turn invokes module's private method) on module in class method style is possible or not? If possible, then what rectifications are required in my code to do the same?
It works when you include the module in a class, because then all of the module's methods get included in that class (the self in module_func_a points to MyClass, which has also the private_b method).
In the other situation self points to MyModule, which does not have private_b method. If you wanted it to work both ways, you'd have to either declare private_b as a module method as well, or simply add the line extend self to MyModule, so that all it's methods would become module methods.
module_function does copy your module_func_a into the metaclass but not its dependencies.
So when calling module_func_a from an object, you get the other method private_b. But calling it on the module itself fails because private_b is not a module function.
You should use module_function for private_b too and it should work.

Resources