Why 'self' method of module cannot become a singleton method of class?
If you want to have both class methods and instance methods mixed into a class when including a module, you may follow the pattern:
module YourModule
module ClassMethods
def a_class_method
puts "I'm a class method"
end
end
def an_instance_method
puts "I'm an instance method"
end
def self.included(base)
base.extend ClassMethods
end
end
class Whatever
include YourModule
end
Whatever.a_class_method
# => I'm a class method
Whatever.new.an_instance_method
# => I'm an instance method
Basically to over-simplify it, you extend
to add class methods and you include
to add instance methods. When a module is included, it's #included
method is invoked, with the actual class it was included in. From here you can extend
the class with some class methods from another module. This is quite a common pattern.
See also: http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
Why a module's singleton method is not visible in downstream eigenclasses where it gets mixed?
First of all, include
does not include eigenclass methods as you might expect. Consider:
module Foo
class << self
def do_something
puts "Foo's eigenclass method does something"
end
end
end
module Bar
include Foo
end
puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)
Note that this is consistent with the behavior of classically defined class methods:
module Foo
def self.do_something
puts "Foo's class method does something"
end
end
module Bar
include Foo
end
puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)
A common idiom is to define the class methods in a submodule and then trigger a call to extend
when the module is included:
module Foo
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def do_something
puts "Foo::ClassMethod's instance method does something"
end
end
end
module Bar
include Foo
end
puts Bar.do_something
# Foo::ClassMethod's instance method does something
The second thing to note is, that you are really including the instance methods of Automobile
into the eigenclass of Vehicle
, thus the instance methods of Automobile
turn into (eigen)class methods of Vehicle
.
Your Car
class basically has nothing to do with all this. The only thing to note here is, that class inheritance also makes class methods available, whereas include
does not. Example:
class Foo
def self.do_something
puts "Foo's class method does something"
end
end
class Bar < Foo
end
puts Bar.do_something
# "Foo's class method does something"
Not use self in every class method and not use singleton model in ruby
(this was already mentioned by engineersmnky in the comments)
You could extend your class with a module that holds your class methods (that module can be nested right within your class):
class Foo
module ClassMethods
def bar
# Do something
end
end
extend ClassMethods
end
You can also move it outside your class, even in its own file (this can be useful structure-wise or if there are many class methods):
# foo/class_methods.rb
class Foo
module ClassMethods
def bar
# Do something
end
end
end
# foo.rb
class Foo
extend ClassMethods
end
Methods defined via extend
can even be overridden in the base class:
class Foo
module ClassMethods
def bar
123
end
end
end
class Foo
extend ClassMethods
def self.bar
super * 2
end
end
Foo.bar #=> 246
This is especially useful if you want to add custom functionality when extending multiple classes with the same module (think of shared class methods).
When to use self in module's methods
Use self
in each method definition if you want the methods to be defined only in the singleton class of the module (where the methods defined using self
live). Omit self and extend self
if you want the methods of the module to be defined as instance methods and singleton methods at the same time.
For instance, you can call the method using RG::Stats.sum(array)
and still have it listed by the instance_methods
method if you do this:
module RG::Stats
extend self
def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end
This way, the sum
method is defined as an instance method and it is included in the singleton class of the module after using extend self
.
You can check the instance methods of RG::Stats
module to verify this:
RG::Stats.instance_methods
=> [:sum]
With this technique you don't have to worry about defining the method without the self
keyword because modules can't have instances so it cannot be called like an instance method of RG::Stats
module. It can only be called as a singleton method RG::Stats.sum(array)
thanks to the extend self
statement.
Ruby Singleton, module vs class
The simplest way to get an object in Ruby is to use, well, an object:
class << Foo = Object.new
attr_accessor :foo
end
Using either a module or a class is overkill, both have features you don't need.
Why do methods inside a class become instance methods instead of becoming singleton methods of the class itself?
It works similarly to message sends and constant lookup:
- The general format of a message send is
foo.bar
, which sends the messagebar
tofoo
. If you leave outfoo
, the message will be sent to the default receiver (which isself
). - The general format of a constant lookup is
Foo::Bar
, which looks up the constantBar
in the moduleFoo
. If you leave outFoo
, the constant will be looked up in the default constant context (or cref). The general format of a method definition is
def foo.bar
, which defines the methodbar
in the singleton class offoo
. If you leave outfoo
, the method will be defined in the default definition context (or default definee):- At the top-level, the default definee is
Object
. (Also, the methods becomeprivate
.) - Within a module declaration body, the default definee is
self
(and notself
's singleton class, like you assumed!) - Within a method body, the default definee is the syntactically enclosing module. (Put another way:
def
doesn't change the default definee.) instance_eval
changes the default definee to the receiver's singleton classclass_eval
changes the default definee to the receiver
- At the top-level, the default definee is
In Ruby, in a method defined in class self, why can't a constant defined on the superclass be access without self?
You have encountered a common Ruby gotcha - constant lookup.
The most important concept in constant lookup is Module.nesting
(unlike in method lookup, where the primary starting point is self
). This method gives you the current module nesting which is directly used by the Ruby interpreter when resolving the constant token. The only way to modify the nesting is to use keywords class
and module
and it only includes modules and classes for which you used that keyword:
class A
Module.nesting #=> [A]
class B
Module.nesting #=> [A::B, A]
end
end
class A::B
Module.nesting #=> [A::B] sic! no A
end
In meta programming, a module or class can be defined dynamically using Class.new
or Module.new
- this does not affect nesting and is an extremely common cause of bugs (ah, also worth mentioning - constants are defined on the first module of Module.nesting):
module A
B = Class.new do
VALUE = 1
end
C = Class.new do
VALUE = 2
end
end
A::B::VALUE #=> uninitialized constant A::B::VALUE
A::VALUE #=> 2
The above code will generate two warnings: one for double initialization of constant A::VALUE and a second for reassigning the constant.
If it looks like "I'd never do that" - this also applies to all the constants defined within RSpec.describe
(which internally calls Class.new), so if you define a constant within your rspec tests, they are most certainly global (unless you explicitly stated the module it is to be defined in with self::
)
Now let's get back to your code:
class SubExample < SuperExample
puts Module.nesting.inspect #=> [SubExample]
class << self
puts Module.nesting.inspect #=> [#<Class:SubExample>, SubExample]
end
end
When resolving the constant, the interpreter first iterates over all the modules in Module.nesting
and searches this constant within that module. So if nesting is [A::B, A]
and we're looking for the constant with token C
, the interpreter will look for A::B::C
first and then A::C
.
However, in your example, that will fail in both cases :). Then the interpreter starts searching ancestors of the first (and only first) module in Module.nesting. SubrExample.singleton_class.ancestors
gives you:
[
#<Class:SubExample>,
#<Class:SuperExample>,
#<Class:Object>,
#<Class:BasicObject>,
Class,
Module,
Object,
Kernel,
BasicObject
]
As you can see - there is no SuperExample
module, only its singleton class - which is why constant lookup within class << self
fails (print_constant_fails
).
The ancestors of Subclass
are:
[
SubExample,
SuperExample,
Object,
Kernel,
BasicObject
]
We have SuperExample
there, so the interpreter will manage to find SuperExample::A_CONSTANT
within this nesting.
We're left with print_constant_works_2
. This is an instance method on a singleton class, so self
within this method is just SubExample
. So, we're looking for SubExample::A_CONSTANT
- constant lookup firstly searches on SubExample
and, when that fails, on all its ancestors, including SuperExample
.
Calling a singleton method within an instance method in a module that extends itself
Kernel.abort
is defined by first defining an instance method Kernel#abort
and then making it also a singleton method with module_function
. (This is definitely the case in Rubinius; I couldn't find it in the MRI source but see below.) module_function
makes a copy of the method. When you redefine abort
you redefine the instance method but not the singleton copy.
Object
includes Kernel
, so when you say abort
you get the instance method, which you've redefined, but when you say Kernel.abort
you get the singleton method, which you haven't redefined.
If you really wanted to use recursion in abort
, or just to demonstrate that this explanation is correct, call module_function :abort
after redefining the method. The singleton method will be updated to be the same as the instance method and both methods will recurse.
Note that you didn't need to extend self
to redefine the instance version of abort
. Since Kernel
is already included in Object
, you only needed to redefine the instance method for all objects to see the redefined version. On the other hand, if Kernel
had used extend self
to expose #abort
in the first place, we could redefine it without any complications.
The following demonstrates that the lack of recursion happens with user-defined, pure Ruby methods, i.e. that module_function
is responsible and native methods are not:
$ cat foo.rb
module Foo
def bar
puts "old version"
end
module_function :bar
end
module Foo
def bar
puts "new version"
Foo.bar
end
end
Object.include Foo
bar
$ ruby foo.rb
new version
old version
Why am I able to call the class method as if it were an instance method here?
When inside an abstract class, the self
refers to the proper class, not the object. That's why you can access the method without explicitly telling self
class self idiom in Ruby
First, the class << foo
syntax opens up foo
's singleton class (eigenclass). This allows you to specialise the behaviour of methods called on that specific object.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Now, to answer the question: class << self
opens up self
's singleton class, so that methods can be redefined for the current self
object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods:
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
This can also be written as a shorthand:
class String
def self.value_of obj
obj.to_s
end
end
Or even shorter:
def String.value_of obj
obj.to_s
end
When inside a function definition, self
refers to the object the function is being called with. In this case, class << self
opens the singleton class for that object; one use of that is to implement a poor man's state machine:
class StateMachineExample
def process obj
process_hook obj
end
private
def process_state_1 obj
# ...
class << self
alias process_hook process_state_2
end
end
def process_state_2 obj
# ...
class << self
alias process_hook process_state_1
end
end
# Set up initial state
alias process_hook process_state_1
end
So, in the example above, each instance of StateMachineExample
has process_hook
aliased to process_state_1
, but note how in the latter, it can redefine process_hook
(for self
only, not affecting other StateMachineExample
instances) to process_state_2
. So, each time a caller calls the process
method (which calls the redefinable process_hook
), the behaviour changes depending on what state it's in.
Related Topics
Puppet/Facter "Could Not Retrieve Fact Fqdn": How to Fix or Circumvent
How to Find the Path a Ruby Gem Is Installed at (I.E. Gem.Lib_Path C.F. Gem.Bin_Path)
Check If a Hash's Keys Include All of a Set of Keys
Ruby: How to Iterate Over an Array of Hashes and Return the Values in a Single String
How to Login a User with Devise
How to Describe an Enumeration Column in a Rails 3 Migration
How to Convert an Array of Strings into a Comma-Separated String
Partial Haml Templating in Ruby Without Rails
Rspec: How to Test File Operations and File Content
How to Get Constants Defined by Ruby's Module Class via Reflection
Nicely Formatting Output to Console, Specifying Number of Tabs
Bcrypt Error: Devise Ruby 2.0 and Rails 4.0
Sidekiq Configuration for Multiple Environments
Getting Rails Url Helpers to Automatically Output Https Urls
M Hartl's Ruby on Rails Tutorial Chapter 5 Custom Title on Home Page
Rails: How to Make Date Strftime Aware of the Default Locale