Class method's has a fuzzy meaning and a sharp meaning

David A. Black in his book - “The Well-Grounded Rubyist”

“So class method has a fuzzy meaning and a sharp meaning. Fuzzily, any
method that gets called directly on a Class object is a class method.
Sharply, a class method is defined, not just called, directly on a Class
object. You’ll hear it used both ways, and as long as you’re aware of
the underlying engineering and can make the sharp distinctions when you
need to, you’ll be fine.”

As a beginner couldn’t take the concept at all. So anyone out there -
could you help me the above with some examples?

Can anyone help me here please?

Why did you change your name from “Love You Ruby”? I preferred that
name.

All I think this is just talking about the contexts of a class method
(hard
to say without knowing what’s being talked about currently in the book).
For example he’s saying the following are referred to as class methods

class Foo
def self.bar # Sharply, a class method is defined, not just called,
directly on a Class object. self is the class Foo here
puts “bar”
end
end

Foo.bar # Fuzzily, any method that gets called directly on a Class
object
is a class method.

Not sure why he uses these terms, they seem more confusing to me than
they
are worth.

2013/2/21 Xavier R. [email protected]

@Matt and @Florian - to both you thank you very much. Now understood it
in all way.

You are very helpful. :slight_smile:

Hi,

Actually, I groked that concept after I understood that “instance
methods”
are actually the special ones.

I’ll ignore Modules for this explanation. They make things a tiny bit
more
complex, but without a lot of conceptual gain.

In Ruby, callable methods are bound to objects. Classes are objects, so
they
have methods. Those methods are defined directly on the object itself.

All of the following 3 are equivalent:

class Foo
def self.bar #self is “Foo” in this context!
end

def Foo.bar
end

a = self
def a.bar
end
end

Which means that they can be directly called:

Foo.bar

Takeaway: you can, at any time, define a method on any object in Ruby.
Even
on classes.

Now, the real problem - and thats where the Class/Object distinction
comes into
play: how do I define methods on Objects that do not exist yet?

Thats what instance methods do: you define a method without an explicit
object.

class Foo
def bar

end
end

If we inspect those two methods, they have an interesting difference:

[3] pry(main)> Foo.method(:bar)
=> #<Method: Foo.bar>
[4] pry(main)> Foo.instance_method(:bar)
=> #<UnboundMethod: Foo#bar>

The first one is bound to an object (the class Foo) and thus can be
called on it.

The second on is unbound, which also means that it cannot be called,
because
it is not bound yet, making things like “self” meaningless:

[5] pry(main)> Foo.method(:bar).call
=> nil
[6] pry(main)> Foo.instance_method(:bar).call
NoMethodError: undefined method `call’ for #<UnboundMethod:
Foo#bar>…

Now, the special ability of classes comes into play: they can be
instantiated, which
means that they can create objects that gain all those instance methods
as normal
methods:

[7] pry(main)> Foo.new.method(:bar)
=> #<Method: Foo#bar>

Note the slightly different notation: thats Foo#bar, the instance
methods, not Foo.bar,
the class method.

So, I usually remember the whole system using 2 simple rules:

  • You can define and call methods on objects
  • You can define methods that serve as templates for methods that
    future objects
    will gain. Those are instance methods.

I hope that helped.

Regards,
Florian

P.S.: You can really define methods on any object at any time:

[11] pry(main)> def bla
[11] pry(main)* s = “string”
[11] pry(main)* def s.really?
[11] pry(main)* “yes”
[11] pry(main)* end
[11] pry(main)* s
[11] pry(main)* end
=> nil
[12] pry(main)> bla.really?
=> “yes”

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs