On Fri, Feb 22, 2013 at 8:53 PM, Florian G. [email protected]
wrote:
Actually, I groked that concept after I understood that “instance methods”
are actually the special ones.
I agree to all else you wrote and your examples but I disagree with
the statement above. At least, I view this differently: all methods
(even class methods) are instance methods because they are stored in
some kind of class. The usual way to define a method is
class X
def foo
end
end
and
module Y
def foo
end
end
All instances which inherit X or Y will have the method. Note that
this is also true if X is really Class or Module which means that
instances of X would be classes or modules.
irb(main):002:0> class Class
irb(main):003:1> def m; “this is a class method” end
irb(main):004:1> end
=> nil
irb(main):005:0> String.m
=> “this is a class method”
irb(main):006:0> Fixnum.m
=> “this is a class method”
Analogous for Module.
The distinction David is aiming at is this: method m from the example
above is the one that is fuzzily called “class method” because it can
be invoked on any class but is not necessarily defined on a class:
irb(main):007:0> Class.ancestors
=> [Class, Module, Object, Kernel, BasicObject]
irb(main):008:0> class Module
irb(main):009:1> def x; “for classes and modules” end
irb(main):010:1> end
=> nil
irb(main):011:0> String.x
=> “for classes and modules”
irb(main):012:0> Enumerable.x
=> “for classes and modules”
The strict ones are really singleton methods defined on a class object:
irb(main):013:0> def String.z; “singleton method on a class” end
=> nil
irb(main):014:0> String.z
=> “singleton method on a class”
But singleton methods can be defined on any instance - a class or
module is just a special case here:
irb(main):015:0> o = Object.new
=> #Object:0x802a6414
irb(main):016:0> def o.s; “singleton method on a non class and non
module object” end
=> nil
irb(main):017:0> o.s
=> “singleton method on a non class and non module object”
In all cases - object, class and module - the method definition is
stored in a special class which you normally do not get to see:
irb(main):018:0> String.singleton_class
=> #Class:String
irb(main):019:0> String.singleton_class.instance_method :z
=> #<UnboundMethod: #Class:String#z>
irb(main):020:0> String.method :z
=> #<Method: String.z>
irb(main):021:0> o.singleton_class
=> #<Class:#Object:0x802a6414>
irb(main):022:0> o.singleton_class.instance_method :s
=> #<UnboundMethod: #<Class:#Object:0x802a6414>#s>
irb(main):023:0> o.method :s
=> #<Method: #Object:0x802a6414.s>
The alternative syntax to define singleton methods reflects that.
Instead of def o.s we can do
irb(main):024:0> class <<o; p self; def t; “another singleton method”
end end
#<Class:#Object:0x802a6414>
=> nil
irb(main):025:0> o.t
=> “another singleton method”
Note the “p” is there just to show it’s the same class as was returned
from o.singleton_method.
So even in this case the method definition is stored in a class,
albeit a special class which only has one instance:
irb(main):026:0> o.singleton_class.new
TypeError: can’t create instance of singleton class
from (irb):26:in new' from (irb):26 from /usr/bin/irb:12:in
’
There is no way I am aware of to make it have more instances:
irb(main):027:0> q = o.dup
=> #Object:0x8022ef40
irb(main):028:0> q.singleton_class.equal? o.singleton_class
=> false
irb(main):029:0> q.singleton_class
=> #<Class:#Object:0x8022ef40>
irb(main):030:0> o.singleton_class
=> #<Class:#Object:0x802a6414>
irb(main):031:0> q = o.clone
=> #Object:0x802e9db8
irb(main):032:0> q.singleton_class
=> #<Class:#Object:0x802e9db8>
irb(main):033:0> q.singleton_class.equal? o.singleton_class
=> false
irb(main):034:0> ObjectSpace.each_object(o.singleton_class) {|o| p o}
#Object:0x802a6414
=> 1
But o and q share singleton methods:
irb(main):035:0> q.s
=> “singleton method on a non class and non module object”
irb(main):036:0> q.t
=> “other singleton method”
And incidentally they share the same definition of those singleton
methods
irb(main):037:0> o.method(:s).unbind
=> #<UnboundMethod: #<Class:#Object:0x802a6414>#s>
irb(main):038:0> q.method(:s).unbind
=> #<UnboundMethod: #<Class:#Object:0x802a6414>#s>
irb(main):039:0> o
I can override one and the other stays intact
irb(main):041:0> def o.s; “overridden” end
=> nil
irb(main):042:0> o.s
=> “overridden”
irb(main):043:0> q.s
=> “singleton method on a non class and non module object”
irb(main):044:0> o.method(:s).unbind
=> #<UnboundMethod: #<Class:#Object:0x802a6414>#s>
irb(main):045:0> q.method(:s).unbind
=> #<UnboundMethod: #<Class:#Object:0x802a6414>#s>
Cheers
robert