Forum: Ruby Class method's has a fuzzy meaning and a sharp meaning

Posted by Xavier R. (arup_r)
on 2013-02-21 21:09
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?
Posted by Xavier R. (arup_r)
on 2013-02-22 19:32
Can anyone help me here please?
Posted by Joel Pearson (virtuoso)
on 2013-02-22 20:13
Why did you change your name from "Love You Ruby"? I preferred that 
name.
Posted by Matt Mongeau (halogenandtoast)
on 2013-02-22 20:16
(Received via mailing list)
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. <lists@ruby-forum.com>
Posted by Florian Gilcher (skade)
on 2013-02-22 20:53
(Received via mailing list)
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"
Posted by Xavier R. (arup_r)
on 2013-02-22 20:59
@Matt and @Florian - to both you thank you very much. Now understood it 
in all way.

You are very helpful. :)
Posted by Robert Klemme (robert_k78)
on 2013-02-23 12:54
(Received via mailing list)
On Fri, Feb 22, 2013 at 8:53 PM, Florian Gilcher <flo@andersground.net> 
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 `<main>'

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
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.