Ruby class << abcd syntax - ruby

I know there have been other questions about the syntax class << self. Still, I did not find those answers clear enough. I have a background in Java/C#, C, so Ruby is kinda strange to me. I read that class << self refers to the singleton class. I find this kinda complex so I would like to understand what does the operator << do in this context and what is possible to put on both ends. I tried to write a simple code to help me understand this syntax (my questions are in the code):
class Self
def Self.selfTest
end
def onSelf
class << Self #I know this might be strange.
self
end
end
def onself
class << self
self
end
end
end
s = Self.new
onSelf = s.onSelf
onself = s.onself
#Here, i wanna know what kind of references are returned.
puts "onSelf responds to onSelf:#{onSelf.respond_to?(:onSelf)}"
puts "onSelf responds to selfTest:#{onSelf.respond_to?(:selfTest)}"
puts "onself responds to onSelf:#{onself.respond_to?(:onSelf)}"
puts "onself responds to selfTest:#{onself.respond_to?(:selfTest)}"
#Output:
#onSelf responds to onSelf:false
#onSelf responds to selfTest:false
#onself responds to onSelf:false
#onself responds to selfTest:true
#So, i conclude that the second one is a reference to a class. What is the first one???????
puts onSelf
puts onself
#Output
#<Class:Self>
#<Class:#<Self:0x007f93640509e8>>
#What does this outputs mean???????
def onSelf.SelfMet
puts 'This is a method defined on base class'
end
def onself.selfMet
puts 'This is a method defined on metaclass'
end
puts "Does Self Class respond to SelfMet? : #{Self.respond_to?(:SelfMet)}"
puts "Does Self Class respond to selfMet? : #{Self.respond_to?(:selfMet)}"
puts "Does Self instance respond to SelfMet? : #{s.respond_to?(:SelfMet)}"
puts "Does Self instance respond to selfMet? : #{s.respond_to?(:selfMet)}"
#Output
#Does Self Class respond to SelfMet? : false
#Does Self Class respond to selfMet? : false
#Does Self instance respond to SelfMet? : false
#Does Self instance respond to selfMet? : false
#Why won't they respond to defined methods????
Thanks
UPDATED:
Thank you all very much. I have read and tested a lot, so will leave a few considerations. I leave this for future reference and as so, i hope the Ruby experts can correct me if i am wrong. I realised that class << Self refers to the Self singleton class. So, the idiomatic class << abcd, starts the abcd singleton class context. I realised also that the hierarchy of a class singleton class is different from an object singleton class. The hierarchy of a class singleton class follows all singleton classes on a hierarchy. In this case:
singleton Self->singleton Object->Singleton basicobject ->class->module->object->kernel->basicObject
The object singleton class lies in a different kind of hierarchy:
Object singleton->Self->Object->kernel->basicObject
This explains this outputs.

In Ruby, every object has a singleton class. This singleton class has only one instance: the object it belongs to.
Since the singleton class has only ever one instance, and every object has its own singleton class, methods that are defined in this class can only be called on that specific object. Those methods are typically called singleton methods, although that is misleading: there's nothing special about those methods, they are just normal standard instance methods.
Here's an example:
foo, bar, baz = Object.new, Object.new, Object.new
class << foo; def quux; :foo end end
class << bar; def quux; :bar end end
foo.quux # => :foo
bar.quux # => :bar
baz.quux # NoMethodError
Classes are just objects like any other object. So, just like any other object, they have singleton classes. Methods defined in the singleton class of an object that happens to be a class are typically called class methods, although again, there's nothing special about them, they are just singleton methods of an object which happens to be a class, which in turn means they are just regular instance methods of a singleton class which belongs to an object which happens to be a class.
So, if you compare this to something like Java, you can see a duality: in Java, there is only one kind of class but there are two kinds of methods (instance and static). In Ruby, there is only one kind of method (instance) but it can be defined in different kinds of classes (regular and singleton).
I find this kinda complex so I would like to understand what does the operator << do in this context
That's just the syntax for opening up a singleton class as opposed to opening up a class.
and what is possible to put on both ends.
Well, on the left has to be the keyword class and on the right any expression that returns an object.

Perhaps this will help. If you add the following statements you will get the indicated results:
puts onSelf #=> #<Class:Self>
puts Self.singleton_class #=> #<Class:Self>
puts onSelf == Self.singleton_class #=> true
puts onself #=> #<Class:#<Self:0x007fe6330aab10>>
puts s.singleton_class #=> #<Class:#<Self:0x007fe6330aab10>>
puts onself == s.singleton_class #=> true
I see no point in defining a method whose receiver is a metaclass, but that is what you have done:
puts onSelf.SelfMet
#=> This is a method defined on Self's metaclass
puts onself.selfMet
#=> This is a method defined on s's metaclass
Obviously, onSelf (Self.singleton_class) responds to SelfMet (but not to selfmet), and onself (s.singleton_class) responds to selfmet (but not to Selfmet).
For Self to respond to SelfMet, the latter would have to be defined def Self.SelfMet... or def self.SelfMet.. (or one of a few other ways), but it is not.
Similiarly, for s to respond to selfMet, the latter would have to be defined as a normal instance method def selfMet... (in which case all other instances of Self would also respond to it) or defined in s's singleton class: def s.selfMet... (in which case other instances of Self would not respond to it).
In sum, the class Self responds to its singleton methods, as does the instance s respond to its singleton methods; the singleton classes of Self and s do not respond to those respective singleton methods.
The following may help you understand what's going on here. Each p self followed by #=> displays what follows #=> when the statement is executed by Ruby. Notice how the various statements, such as class Dog, class << self and others are used to change the value of self to what we want.
p self is your best friend when metaprogramming.
p self #=> main
class Dog
p self #=> Dog
def self.woof1
p self
end
def Dog.woof2
p self
end
p self #=> Dog
class << self
p self #=> #<Class:Dog>
p Dog.singleton_class #=> #<Class:Dog>
def woof3
p self
end
end
p self #=> Dog
def woof4
p self
end
end
p self #=> main
def Dog.woof5
p self
end
Dog.instance_eval do
p self #=> Dog
def woof6
p self
end
end
dog = Dog.new #=> #<Dog:0x007fe17b08cf00>
def dog.woof7
p self
end
dog.instance_eval do
p self #=> #<Dog:0x007fe17b08cf00>
def woof8
p self
end
end
p self #=> main
Dog.woof1 #=> Dog
Dog.woof2 #=> Dog
Dog.woof3 #=> Dog
Dog.woof5 #=> Dog
Dog.woof6 #=> Dog
dog.woof4 #=> #<Dog:0x007fe17b08cf00>
dog.woof7 #=> #<Dog:0x007fe17b08cf00>
dog.woof8 #=> #<Dog:0x007fe17b08cf00>
puppy = Dog.new #=> #<Dog:0x007fe17ba93a08>
puppy.woof4 #=> #<Dog:0x007fe17ba93a08>
puppy.woof7 #=> undefined method `woof7' for #<Dog:0x007fe5fb3e1d48>
puppy.woof8 #=> undefined method `woof8' for #<Dog:0x007fe5fb3e1d48>
It takes awhile to sort everything out. Even then, most of us need a refresher from time-to-time. Here's an excellent article on the subject. Also, look at some of the references in the comments there, especially Dave Thomas' presentation.
Lastly, have a look at Ruby's naming convention.

Related

When do I need to use self.instance_method vs instance_method alone?

I'm hoping someone can explain why I get the same behavior from both of these methods and what that means for when to or not to use self.
def my_instance_method(arg)
'execute some code' if another_instance_method_of_same_class?(arg)
end
seems to behave exactly the same as
def my_instance_method(arg)
'execute some code' if self.another_instance_method_of_same_class?(arg)
end
My apologies if my search skills aren't up to par but I couldn't find the exact answer to this question, just explanations of what self does (which made me think I should need it).
I'm using the latest version of Ruby. Thank you.
There are a few differences between self.foo(...) and foo(...), but they're mostly equivalent.
Privacy
private methods can only be called via foo directly, and never with an explicit receiver. So if foo is marked private, then you have to call it without self.
class Example
private def foo(x)
x + 1
end
def bar
foo # Works fine
self.foo # Error: foo is private
end
end
Shadowing
If you have a local variable called foo in the current function, then writing foo without arguments will reference the local variable instead
class Example
def foo(*args)
puts "Hello :)"
end
def bar
foo = 100 # Just an ordinary variable; no relation to the above method
foo # This refers to the local variable called "foo"
self.foo # This calls the method foo() with no arguments
foo(1) # This calls the method foo() with one argument
self.foo(1) # Equivalent to the above; calls with one argument
end
def baz
foo # There's no local variable called "foo", so this calls the method
end
end
Assignment
If the method you're talking about is an assignment method (i.e. ends in =), then it must always be called with an explicit receiver
class Example
def foo=(value)
puts "Assigning foo = #{value}"
end
def bar
foo = 0 # This creates a new local variable called foo and assigns to it
self.foo = 0 # Calls foo= on self
end
end
I will answer your question, but that will not help you understand when you are to use the prefix self. when defining methods. I therefore need to first present some background information on instance methods.
Suppose we have the following class definition.
class C
puts "self = #{self}
def i
puts "self in i = #{self}"
"i"
end
def self.c
puts "self in c = #{self}"
"c"
end
singleton_class.define_method(:s) do
puts "self in s = #{self}"
"s"
end
end
#=> :s
self = C
I have defined an instance method C#i, a class method C::c and an instance method on C singleton class, s.
Note that, since self #=> C within the class, writing def self.c ... is precisely the same as def C.c .... The only reasons for writing self is that if we rename the class we don't have to change def self.c ... and
"self" is harder to misspell than, say, "PhilharmonicOrchestras".
Unsurprisingly,
C.instance_methods(false)
#=> [:i]
instance = C.new
#=> #<C:0x00007ff0011074f0>
instance.i
#=> "i"
self in i = #<C:0x00007ff0011074f0>
Now consider the last two methods:
C.methods(false)
#=> [:s, :c]
C.c
#=> "c"
self in c = C
C.singleton_class.instance_methods(false)
#=> [:s, :c]
C.s
#=> "s"
self in s = C
This shows that defining a method def self.class.c is merely a shorthand way of telling Ruby that you wish to create an instance method s on C's singleton class. Similarly, references to "class methods" are shorthand for those same instance methods. In fact, there is no need to define methods with the prefix self.. You could instead use singleton_class and define_method, as I have done, or elect one of several other ways, the most common being
class C
class << self
def s
puts "self in s = #{self}"
"s"
end
end
end
where class << self .. end causes self to change from C to C.singleton_class.
You defined a method which I will modify a bit:
self
#=> main
def my_instance_method
puts "self = #{self}, self.class = #{self.class}"
'execute some code'
end
my_instance_method
#=> "execute some code"
self = main, self.class = Object
As all methods are instance methods this must be one as well, namely a private instance method of Object:
Object.private_instance_methods.include?(:my_instance_method)
#=> true
Being a private instance method we cannot invoke it on an explicit receiver that is an instance of Object (main), but we can write:
Object.new.send(:my_instance_method)
#=> "execute some code"
self = #<Object:0x00007f988514e180>, self.class = Object
Note that if it were made a public method it would be available for use by all objects, which obviously would lead to disaster.
Next consider:
def self.your_instance_method
puts "self = #{self}, self.class = #{self.class}"
'execute some code'
end
your_instance_method
#=> "execute some code"
self = main, self.class = Object
This method must be defined on self's (main's) singleton class, which we may confirm:
self.singleton_class.instance_methods.include?(:your_instance_method)
#=> true
Therefore, the implicit receiver of
your_instance_method
is self, which equals main, giving the same result as
self.send(:your_instance_method)
This is a complicated subject (concerning Ruby's Object Model), particularly for someone fairly new to Ruby, so don't be concerned if you are not able to follow all of what I have said.

Having a module singleton extending a class

I have a singleton in my application that gets reused across applications. I want that singleton to get some default methods from my class, but also be able to customize the module/eigenclass. Most of all, I don't want to call up instance on every call the the utility singleton.
Here's an example. Let's say my default class is Universe::Earth. Then I want an Earth module in my application that "extends" that class.
module Universe
class Earth
def self.grow!
#grown = true
end
end
end
module Earth
class < Universe::Earth << self; end
grow!
end
When that's run, grow! is a NoMethodError.
Tried those approaches:
Class.new(Goodluck::Contest) << self
class < Universe::Earth << self; end
extend Universe::Earth
How do I make it work?
Is this the sort of thing you are looking for?
module Universe
class Earth
def self.grow!
#grown = true
end
end
end
module Earth
Universe::Earth.class_eval do
define_method(:instance_howdy) do
puts "instance_howdy!"
end
end
def (Universe::Earth).class_howdy
puts "class_howdy!"
end
end
Universe::Earth.methods(false) #=> [:grow!, :class_howdy]
Universe::Earth.instance_methods(false) #=> [:instance_howdy]
Universe::Earth.new.instance_howdy #=> instance_howdy!
Universe::Earth.class_howdy #=> class_howdy!
[Edit: If you just want to set #grown => true, and retrieve it's value, you merely need:
module Earth
Universe::Earth.grow! #=> true
end
Verify:
Universe::Earth.instance_variable_get("#grown") #=> true
If you wish to also add an accessor for the class instance variable, you could do this:
def add_class_accessor(c, accessor, var)
c.singleton_class.class_eval("#{accessor} :#{var}")
end
Universe::Earth.methods(false)
#=> [:grow!]
module Earth
Universe::Earth.grow! #=> true
add_class_accessor(Universe::Earth, "attr_accessor", "grown")
end
Universe::Earth.methods(false)
#=> [:grow!, :grown, :grown=]
Universe::Earth.grown
#=> true
Universe::Earth.grown = "cat"
#=> "cat"
Universe::Earth.grown
#=> "cat"
Object#singleton_class was added in Ruby 1.9.2. For earlier versions you could do this:
def add_class_accessor(c, accessor, var)
eigenclass = class << c; self; end
eigenclass.class_eval("#{accessor} :#{var}")
end
You might consider putting add_class_accessor in a module to be included as needed. Other methods you might add to the same module might be:
add_instance_method(klass, method, &block)
add_class_method(klass, method, &block)
add_instance_accessor(klass, accessor, var)
:tidE

Dynamically creating class method

I am writing a class method to create another class method. There seems to be some strangeness around how class_eval and instance_eval operate within the context of a class method. To illustrate:
class Test1
def self.add_foo
self.class_eval do # does what it says on the tin
define_method :foo do
puts "bar"
end
end
end
end
Test1.add_foo # creates new instance method, like I'd expect
Test1.new.foo # => "bar"
class Test2
def self.add_foo
self.instance_eval do # seems to do the same as "class_eval"
define_method :foo do
puts "bar"
end
end
end
end
Test2.add_foo # what is happening here?!
Test2.foo # => NoMethodError
Test2.new.foo # => "bar"
class Test3
def self.add_foo
(class << self; self; end).instance_eval do # call explicitly on metaclass
define_method :foo do
puts "bar"
end
end
end
end
Test3.add_foo # => creates new class method, as I'd expect
Test3.foo # => "bar"
My understanding is that class methods are instance methods defined on the metaclass of the class in question (Test2 in this case). Based on that logic, I would expect the receiver for the class method call add_foo to be the metaclass.
What is self referring to inside the Test2.add_foo method?
Why does calling instance_eval on this receiver object create an instance method?
The main difference between instance_eval and class_eval is that instance_eval works within the context of an instance, while class_eval works within the context of a class. I am not sure how familiar you are with Rails, but let's look at this for an example:
class Test3 < ActiveRecord::Base
end
t = Test3.first
t.class_eval { belongs_to :test_25 } #=> Defines a relationship to test_25 for this instance
t.test_25 #=> Method is defined (but fails because of how belongs_to works)
t2 = Test3.find(2)
t2.test_25 #=> NoMethodError
t.class.class_eval { belongs_to :another_test }
t.another_test #=> returns an instance of another_test (assuming relationship exists)
t2.another_test #=> same as t.another_test
t.class_eval { id } #=> NameError
t.instance_eval { id } #=> returns the id of the instance
t.instance_eval { belongs_to :your_mom } #=> NoMethodError
This happens because belongs_to is actually a method call that happens within the context of the class body, which you cannot call from an instance. When you try to call id with class_eval, it fails because id is a method defined on an instance, not in a class.
Defining methods with both class_eval and instance_eval work essentially the same when called against an instance. They will define a method only on the instance of the object it is called against.
t.class_eval do
def some_method
puts "Hi!"
end
end
t.instance_eval do
def another_method
puts "Hello!"
end
end
t.some_method #=> "Hi!"
t.another_method #=> "Hello!"
t2.some_method #=> NoMethodError
t2.another_method #=> NoMethodError
They differ, however, when dealing with the class.
t.class.class_eval do
def meow
puts "meow!"
end
end
t.class.instance_eval do
def bark
puts "woof!"
end
end
t.meow #=> meow!
t2.meow #=> meow!
t.bark #=> NoMethodError
t2.bark #=> NoMethodError
So where did bark go? It got defined on the instance of the class' singleton class. I'll explain more below. But for now:
t.class.bark #=> woof!
Test3.bark #=> woof!
So to answer your question about what self is referring to within the class body, you can construct a little test:
a = class Test4
def bar
puts "Now, I'm a #{self.inspect}"
end
def self.baz
puts "I'm a #{self.inspect}"
end
class << self
def foo
puts "I'm a #{self.inspect}"
end
def self.huh?
puts "Hmmm? indeed"
end
instance_eval do
define_method :razors do
puts "Sounds painful"
end
end
"But check this out, I'm a #{self.inspect}"
end
end
puts Test4.foo #=> "I'm a Test4"
puts Test4.baz #=> "I'm a Test4"
puts Test4.new.bar #=> Now I'm a #<Test4:0x007fa473358cd8>
puts a #=> But check this out, I'm a #<Class:Test4>
So what is happening here is that in the first puts statement above, we see that inspect is telling us that self within the context of a class method body is referring to the class Test4. In the second puts, we see the same thing, it's just defined differently (using the self.method_name notation for defining class methods). In the third, we see that self refers to an instance of Test4. The last one is a bit interesting because what we see is that self is referring to an instance of Class called Test4. That is because when you define a class, you're creating an object. Everything in Ruby is an object. This instance of object is called the metaclass or the eigenclass or singleton class.
You can access the eigenclass with the class << self idiom. While you're in there, you actually have access to the internals of the eigenclass. You can define instance methods inside of the eigenclass, which is congruent with calling self.method_name. But since you are within the context of the eigenclass, you can attach methods to the eigenclass' eigenclass.
Test4.huh? #=> NoMethodError
Test4.singleton_class.huh? #=> Hmmm? indeed
When you call instance_eval in the context of a method, you're really calling instance_eval on the class itself, which means that you are creating instance methods on Test4. What about where I called instance_eval inside of the eigenclass? It creates a method on the instance of Test4's eigenclass:
Test4.razors #=> Sounds painful
Hopefully, this clears up a few of your questions. I know that I have learned a few things typing out this answer!

Ruby Singleton methods for class and objects

I am learning Ruby Singletons and i found some ways to define and get list of Class and Object singleton methods.
Class Singleton Methods
Ways to define class singleton methods:
class MyClass
def MyClass.first_sing_method
'first'
end
def self.second_sing_method
'second'
end
class << self
def third_sing_method
'third'
end
end
class << MyClass
def fourth_sing_method
'fourth'
end
end
end
def MyClass.fifth_sing_method
'fifth'
end
MyClass.define_singleton_method(:sixth_sing_method) do
'sixth'
end
Ways to get list of class singletons methods:
#get singleton methods list for class and it's ancestors
MyClass.singleton_methods
#get singleton methods list for current class only
MyClass.methods(false)
Object Singleton Methods
Ways to define object singleton methods
class MyClass
end
obj = MyClass.new
class << obj
def first_sing_method
'first'
end
end
def obj.second_sing_method
'second'
end
obj.define_singleton_method(:third_sing_method) do
'third'
end
Way to get list of object singleton methods
#get singleton methods list for object and it's ancestors
obj.singleton_methods
#get singleton methods list for current object only
obj.methods(false)
Are there other ways to do this?
First of all, the way to list singleton methods is with singleton_methods. The methods method returns a list of the names of public and protected methods of the object. Also, it is defined in the Object class. Try extending an instance. It is one of the most elegant ways, as it supports code reuse and seems to me very object-oriented:
class Foo
def bar
puts "Hi"
end
end
module Bar
def foo
puts "Bye"
end
end
f = Foo.new
f.bar
#=> hi
f.extend Bar
f.foo
#=> bye
f.methods(false)
#=> []
# the module we extended from is not a superclass
# therefore, this must be empty, as expected
f.singleton_methods
#=> ["foo"]
# this lists the singleton method correctly
g = Foo.new
g.foo
#=> NoMethodError
Edit: In the comment you asked why methods(false) returns nothing in this case. After reading through the C code it seems that:
methods returns all the methods available for the object (also the ones in included modules)
singleton_methods returns all the singleton methods for the object (also the ones in included modules) (documentation)
singleton_methods(false) returns all the singleton methods for the object, but not those declared in included modules
methods(false) supposedly returns the singleton methods by calling singleton_methods, but it also passes the parameter false to it; whether this is a bug or a feature - I do not know
Hopefully, this clarifies the issue a little. Bottom line: call singleton_methods, seems more reliable.
Some more ways:
Class singleton methods
class << MyClass
define_method :sixth_sing_method do
puts "sixth"
end
end
class MyClass
class << self
define_method :fourth_sing_method do
puts "seventh"
end
end
end
Object singleton methods
class << obj
define_method :fourth_sing_method do
puts "fourth"
end
end
Next, you can use define_method and define_singleton_method in combination with send, e.g.
obj.send :define_singleton_method, :nth_sing_method, lambda{ puts "nth" }
and all possible combinations thereof. To use define_method, you need to capture the singleton class first as in this (the same works for class objects, too)
singleton_class = class << obj; self end
singleton_class.send :define_method, :nth_sing_method, lambda{ puts "nth" }
Another ways is using class_eval on the singleton class objects:
singleton_class.class_eval do
def nth_sing_method
puts "nth"
end
end
And then you once again may combine send with class_eval...
There are myriads of ways, I guess :)
Object singleton methods
instance_eval
class A
end
a = A.new
a.instance_eval do
def v
"asd"
end
end
a.singleton_methods
=> [:z, :v]

Ruby Class Methods vs. Methods in Eigenclasses

Are class methods and methods in the eigenclass (or metaclass) of that class just two ways to define one thing?
Otherwise, what are the differences?
class X
# class method
def self.a
"a"
end
# eigenclass method
class << self
def b
"b"
end
end
end
Do X.a and X.b behave differently in any way?
I recognize that I can overwrite or alias class methods by opening the eigenclass:
irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"
The two methods are equivalent. The 'eigenclass' version is helpful for using the attr_* methods, for example:
class Foo
#instances = []
class << self;
attr_reader :instances
end
def initialize
self.class.instances << self
end
end
2.times{ Foo.new }
p Foo.instances
#=> [#<Foo:0x2a3f020>, #<Foo:0x2a1a5c0>]
You can also use define_singleton_method to create methods on the class:
Foo.define_singleton_method :bim do "bam!" end
In Ruby there really are no such things as class methods. Since everything is an object in Ruby (including classes), when you say def self.class_method, you are just really defining a singleton method on the instance of the class Class. So to answer your question, saying
class X
def self.a
puts "Hi"
end
class << self
def b
puts "there"
end
end
end
X.a # => Hi
X.b # => there
is two ways of saying the same thing. Both these methods are just singeton (eigen, meta, ghost, or whatever you want to call them) methods defined in the instance of your Class object, which in your example was X. This topic is part of metaprogramming, which is a fun topic, that if you have been using Ruby for a while, you should check out.
The Pragmatic Programmers have a great book on metaprogramming that you should definitely take a look at if you interested in the topic.
Yet another necromancer here to unearth this old question... One thing you might not be aware of is that marking a class method as private (using the private keyword instead of :private_class_method) is different than marking an eigenclass method as such. :
class Foo
class << self
def baz
puts "Eigenclass public method."
end
private
def qux
puts "Private method on eigenclass."
end
end
private
def self.bar
puts "Private class method."
end
end
Foo.bar
#=> Private class method.
Foo.baz
#=> Eigenclass public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
# from (irb)
The following example will work how the previous one intends:
class Foo
class << self
def baz
puts "Eigen class public method."
end
private
def qux
puts "Private method on eigenclass."
end
end
def bar
puts "Private class method."
end
private_class_method :bar
end
Foo.bar
#=> NoMethodError: private method `bar' called for Foo:Class
# from (irb)
Foo.baz
#=> Eigen class public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
# from (irb)
Most instance methods used in Ruby are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.
There is an apparent contradiction. Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.
If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.
class Zen
end
z1 = Zen.new
z2 = Zen.new
def z1.say_hello # Notice that the method name is prefixed with the object name
puts "Hello!"
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
In the above example, the say_hello method was defined within the z1 instance of the Zen class but not the z2 instance.
The following example shows a different way to define a singleton method, with the same result.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
In the above example, class << z1 changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.
Both of the above examples serve to illustrate how singleton methods work. There is, however, an easier way to define a singleton method: using a built-in method called define_singleton_method.
class Zen
end
z1 = Zen.new
z2 = Zen.new
z1.define_singleton_method(:say_hello) { puts "Hello!" }
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
We learned earlier that classes are also objects (instances of the built-in class called Class). We also learned about class methods. Class methods are nothing more than singleton methods associated with a class object.
One more example:
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method.
Read more at this post about Ruby Classes.

Resources