What’s the difference between a regular method and a singleton method?
On Dec 21, 2007, at 6:51 PM, Ryan L. wrote:
What’s the difference between a regular method and a singleton method?
From the perspective of a particular object, singleton methods are
those methods that are defined within the singleton class of
the object.
Regular methods are methods that are defined within the normal
inheritance tree of the object’s class.
Method lookup is done by first checking the singleton class of an
object and if not found there by checking the normal inheritance tree.
By default objects don’t have a singleton class. The singleton class
is created when it is referenced:
$ irb
a = [1,2,3]
=> [1, 2, 3]a.second
NoMethodError: undefined method `second’ for [1, 2, 3]:Array
from (irb):2
from :0class <<a
def second
self[1]
end
end
=> nila.second
=> 2[4, 5, 6].second
NoMethodError: undefined method `second’ for [4, 5, 6]:Array
from (irb):9
from :0
In this example, I opened up the singleton class associated
with ‘a’ and defined a new method, second, that returns the
second element of the array. As you can see, this method
is only available to that one particular array and not to
all array’s in general.
Gary W.
Just out of curiosity, is there a difference between
def a.second
…
end
and
class << a
?
Gary W. wrote:
On Dec 21, 2007, at 6:51 PM, Ryan L. wrote:
What’s the difference between a regular method and a singleton method?
From the perspective of a particular object, singleton methods are
those methods that are defined within the singleton class of
the object.Regular methods are methods that are defined within the normal
inheritance tree of the object’s class.Method lookup is done by first checking the singleton class of an
object and if not found there by checking the normal inheritance tree.By default objects don’t have a singleton class. The singleton class
is created when it is referenced:$ irb
a = [1,2,3]
=> [1, 2, 3]a.second
NoMethodError: undefined method `second’ for [1, 2, 3]:Array
from (irb):2
from :0class <<a
def second
self[1]
end
end
=> nila.second
=> 2[4, 5, 6].second
NoMethodError: undefined method `second’ for [4, 5, 6]:Array
from (irb):9
from :0In this example, I opened up the singleton class associated
with ‘a’ and defined a new method, second, that returns the
second element of the array. As you can see, this method
is only available to that one particular array and not to
all array’s in general.Gary W.
On Dec 21, 2007, at 9:59 PM, Ben Lipton wrote:
Now, this is talking about class methods, not singleton methods on
arbitrary
objects, but I think the idea still applies because class methods are
methods on a singleton, in this case the object Parser (which
happens to be
a Class).
I think your description is a bit misleading.
A class method is a singleton method of a class object.
A class is an instance of Class.
What I’m trying to point out is that class objects
are not ‘singletons’ in the sense of the one-and-only
instance of a particular class, which it appears to be
what you were alluding to if I’m not mistaken.
There are many instances of Class: Array, Object,
Parser, Hash, and so on.
This is yet another example where the word ‘singleton’,
as in singleton method and singleton class, can get confused
with the more generic use of singleton (which I don’t
think applies here in any case).
Gary W.
So defining the ‘second’ method like so:
def Array.second
self[1]
end
is the same is making the singleton class like below.
Class << Array
def second
self[1]
end
end
Gotcha.
Thanks for the help! =)
Gary W. wrote:
On Dec 21, 2007, at 6:51 PM, Ryan L. wrote:
In this example, I opened up the singleton class associated
with ‘a’ and defined a new method, second, that returns the
second element of the array. As you can see, this method
is only available to that one particular array and not to
all array’s in general.Gary W.
I think the answer is No, there isn’t a difference, but it’s something
I’ve
been wondering about.
From http://blog.jayfields.com/2007/04/ruby-class-methods.html we have:
“In fact, you can define a class method various ways, but the result is
always an instance method on the singleton class.”
class Parser
def self.self_process(script)
# …
end
def Parser.parser_process(script)
# …
end
class << self
def singleton_process(script)
# …
end
end
def self.singleton
class << self; self; end
end
end
Now, this is talking about class methods, not singleton methods on
arbitrary
objects, but I think the idea still applies because class methods are
methods on a singleton, in this case the object Parser (which happens to
be
a Class). So, the second and the third examples are the ones you’re
asking
about, because inside the “class Parser … end”, self is equal to
Parser.
So, he’s doing
def Parser.parser_process(script)
end
and
class << Parser
def singleton_process(script)
end
end
just like your example.
On Dec 22, 2007, at 1:35 AM, Ryan L. wrote:
end
No. Your examples are different than mine.
In your examples you are defining a singleton method
for ‘Array’, which is an object that just happens
to be a class.
In my examples I defined a singleton method for one
particular array, not all arrays, and not the object
known as Array.
Let’s see if I can summarize things a bit:
All method definitions wind up being stored in a
module of one sort or another (which includes
classes since Class is a subclass of Module,
i.e. every class is also a module).
-
standard modules (instances of Module)
– the methods are called instance methods -
standard classes (instances of Class)
– the methods are called instance methods -
singleton classes of non-class/non-module objects
– the methods are called singleton methods -
singleton classes of instances of Module
– the methods are called module methods or
singleton methods of a (particular) module -
singleton classes of instances of Class
– the methods are called class methods or
singleton methods of a (particular) class.
Since singleton classes are also classes, you can
get an infinite regress of singleton methods of
a singleton class of a singleton class of a…
But just set that aside for the moment. Here is
what the code looks like for the cases I listed:
case 1
module Enumerable
def foo; end
end
case 2
class Array
def foo; end
end
case 3
a = Object.new
def a.foo; end
also case 3
class <<a
def foo; end
end
case 4
def Enumerable.foo
end
also case 4
module Enumerable
def self.foo
end
end
also case 4
module Enumerable
class <<self
def foo; end
end
end
still case 4
class <<Enumerable
def foo; end
end
case 5
def Array.foo
end
also case 5
class Array
def self.foo
end
end
also case 5
class Array
class <<self
def foo; end
end
end
still case 5
class <<Array
def foo; end
end
I hope that helps.
Gary W.
On Dec 21, 2007 11:51 PM, Gary W. [email protected] wrote:
def second self[1] end
end
No.
His question is, “are these the same?” to which the answer is simply
yes.
Pat
Gary W. wrote:
end
end
No.
Yes, actually.
Your examples are different than mine.
They are. They also don’t make much sense. But they’re still equivalent
to each other.
case 5
def Array.foo
end
[…]still case 5
class <<Array
def foo; end
end
See? Both case 5.
On Dec 22, 2007, at 2:59 AM, Sebastian H. wrote:
self[1]
equivalent
to each other.
I was trying to point out that they didn’t make sense relative
to the previous examples in the thread, but Sebastian is correct
to point out that they are equivalent to each other.
It turns out that those definitions for Array.second end
up returning arrays, in particular they return [1], since Array
actually has a [] method, which construct and returns a new array.
In Ryan’s code, self[1], is actually a call to Array.[], which
constructs the new array.
Array.second returns [1] in those examples, something very different
what I was showing in my examples.
Gary.
You’re right, my description is misleading, though I think I had it
correctly in my head. I’m new to Ruby and still figuring out my
terminology.
Thanks for clearing that up.