Class ≪≪ Self VS Self.Method With Ruby: What's Better

class self vs self.method with Ruby: what's better?

class << self is good at keeping all of your class methods in the same block. If methods are being added in def self.method form then there's no guarantee (other than convention and wishful thinking) that there won't be an extra class method tucked away later in the file.

def self.method is good at explicitly stating that a method is a class method, whereas with class << self you have to go and find the container yourself.

Which of these is more important to you is a subjective decision, and also depends on things like how many other people are working on the code and what their preferences are.

Difference between 'self.method_name' and 'class self' in Ruby

The class << self notation opens up the eigenclass of an object. An eigenclass is an anonymous class that stores instance-specific behaviour. In the case of a class an eigenclass is sometimes called a metaclass.

Ruby uses eigenclasses to implement so called 'class methods' (also called static methods).

A Class (as moritz stated) is also an Object in Ruby and in so far as it is an object it also has a class. The class of a class in Ruby is called Class.

A 'class method' in any language is a method in which a class is the receiver - that is the method is directly invoked on the class itself.

However in order for a method to be invoked on a receiver that method must be defined on the class of that receiver. In the case of classes a 'class method' could be implemented as an instance method on the Class class.

But defining an instance method on Class would mean that ALL classes get access to that class method which is not ideal.

Enter the eigenclass, as stated before, the eigenclass for an object is a special class that stores the methods unique to that object. In the case of classes the eigenclass subclasses the Class class and is the direct class of the class.

'class methods' in Ruby therefore are just 'instance methods' defined on the class's eigenclass.

The def MyClass.my_method notation actually defines my_method on the eigenclass of MyClass. If you use this notation you can get by (for a while) without actually understanding eigenclasses since you can trick yourself into thinking it is just Ruby's way of defining 'static methods' and continue thinking Ruby's class model is similar to Java's. However, the class << self notation allows no such interpretation and you must come to terms with the reality of eigenclasses.

In summary, 'class methods' are actually 'instance methods' defined on the eigenclass and the class << self gives you access to the eigenclass.

For more reading check out these links:

http://banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/

http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/

http://www.klankboomklang.com/2007/09/21/the-singleton-class/

Ruby: class self; def method VS. def self.method

Another good reason to use class << self is when you need accessors on the class level:

class Foo
class << self
attr_accessor :bar
end
end

Beware that this is often not what you want as it is not thread safe. But that's a design problem. If you need it, you need it.

What is self in class self and why is this different from the Class instance that is defining this block of code?

Why is self not the same as MyClass inside of the class << self scope.

Because the class keyword always changes the scope:

class MyClass
puts self #=> MyClass

class <<self
puts self #=>MyClass’s singleton class
end
end

More specifically, why is the method delegate not available to self
inside of class << self?

class MyClass

def self.delegate
puts "executing MyClass.delegate()"
end

class <<self
delegate
end

end

--output:--
1.rb:8:in `singleton class': undefined local variable or method `delegate' for #<Class:MyClass> (NameError)
from 1.rb:7:in `<class:MyClass>'
from 1.rb:1:in `<main>'

Note that the following constructs are equivalent:

class MyClass

def self.delegate
puts "executing MyClass.delegate()"
end

end

MyClass.delegate

--output:--
executing MyClass.delegate()

and:

class MyClass

class <<self
def delegate
puts "executing MyClass.delegate()"
end
end

end

MyClass.delegate

--output:--
executing MyClass.delegate()

Therefore, your code is equivalent to:

class MyClass

class <<self
def delegate
puts "executing MyClass.delegate()"
end

delegate
end

end

If you ignore the outer MyClass for a moment, then you defined a class like this:

class <<self
def delegate
puts "executing MyClass.delegate()"
end

delegate
end

That same structure can be replicated like this:

class Dog
def bark
puts “woof”
end

bark
end

which will produce the same type of error:

1.rb:7:in `<class:Dog>': undefined local variable or method `bark' for Dog:Class (NameError)
from 1.rb:1:in `<main>'
  1. When you call a method and you don't specify a receiver, ruby uses whatever object is currently assigned to the self variable as the receiver.

  2. Inside a method, ruby assigns the object that called the method to the self variable. The object that called the method is not the same thing as the class (object) in which the method is defined.

  3. Inside a class, but outside of any method definitions, ruby assigns the class (object) to self.

Note that it is the instances of the Dog class that can call the def's inside the Dog class, e.g. bark(). Similarly, it is the instances of the singleton class that can call the def's inside the singleton class, e.g. delegate()--the singleton class itself cannot call the def's inside the singleton class. The whole reason they are called singleton classes is because singleton classes have only one instance--in your case the one instance of the singleton class is MyClass. As a result, MyClass can call delegate(), but the singleton class cannot call delegate().

I don't understand really what a class method on an eignclass is
however.

Personally, I don't use the term eigenclass. In my opinion, ruby has made a decision that the term is singleton class. If you look through the docs for the Object class, there are no method names that have eigenclass in them, yet there are method names with singleton class in them.

All objects have a singleton class. A singleton class is an object. Therefore, every singleton class also has a singleton class--which means that the chain of singleton classes is infinite:

class Dog
end

s1 = Dog.singleton_class
puts s1

s2 = s1.singleton_class
puts s2

s3 = s2.singleton_class
puts s3

--output:--
#<Class:Dog>
#<Class:#<Class:Dog>>
#<Class:#<Class:#<Class:Dog>>>

Which means you can do stuff like this:

class Dog
class <<self #s1
class <<self #s2
def greet #Instances of s2 can call greet, and the only instance of s2 is s1.
puts "hello"
end
end
end
end


class Dog
class <<self
#Inside here self = Dog's singleton class = s1
greet #equivalent to Dogs_singleton_class.greet
end
end

--output:--
hello

However, I've never seen anyone use a singleton class of a singleton class (s2) before in their code. I did it once to answer a question a long, long time ago, and nobody had any idea what I was talking about.

There are some method lookup diagrams here, which might prove useful.

self vs class name for class methods in inheritance

self is widely used in Ruby Metaprogramming.

From Metaprogramming Ruby book:

Every line of Ruby code is executed inside an object—the so–called
current object. The current object is also known as self, because
you can access it with the self keyword.

Only one object can take the role of self at a given time, but no
object holds that role for a long time. In particular, when you call a
method, the receiver becomes self. From that moment on, all instance
variables are instance variables of self, and all methods called
without an explicit receiver are called on self. As soon as your code
explicitly calls a method on some other object, that other object
becomes self.

So, in code:

class Dog
# self represents the class object i.e: Dog. Which is an instance of Class.
# `bark` will be treated as class method
def self.bark
print "woof"
end
end

can also be written as:

class Dog
# Dog is an instance of Class.
# `bark` will be treated as class method
def Dog.bark
print "woof"
end
end

Inheritance allows a subclass to use features of its parent class. That's why you can access bark method in Little_dog class since it is inherited Dog class:

class Little_dog < Dog
# has `bark` as a class method because of Dog
end

Ruby style guide tip: In Ruby it's considered as a best practice to use CamelCase convention for naming classes and modules.

When to use self in module's methods

Use self in each method definition if you want the methods to be defined only in the singleton class of the module (where the methods defined using self live). Omit self and extend self if you want the methods of the module to be defined as instance methods and singleton methods at the same time.

For instance, you can call the method using RG::Stats.sum(array) and still have it listed by the instance_methods method if you do this:

module RG::Stats
extend self

def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end

This way, the sum method is defined as an instance method and it is included in the singleton class of the module after using extend self.

You can check the instance methods of RG::Stats module to verify this:

RG::Stats.instance_methods
=> [:sum]

With this technique you don't have to worry about defining the method without the self keyword because modules can't have instances so it cannot be called like an instance method of RG::Stats module. It can only be called as a singleton method RG::Stats.sum(array) thanks to the extend self statement.

class method `self.` within class methods block `class self` in Ruby

Each object in Ruby has its own singleton class. This is where all the methods of instances are defined.

Consider the following example.

class C; end
c1, c2 = C.new, C.new
c1.extend(Module.new { def m1; 42; end })

c1.m1
#⇒ 42
c2.m1
#⇒ NoMethodError: undefined method `m1' for #<C:0x000055cb062e6888>

c1.singleton_class.instance_methods.grep /m1/
#⇒ [:m1]
c2.singleton_class.instance_methods.grep /m1/
#⇒ []

Singleton class is needed to make it possible to extend objects etc.

In Ruby, everything is object. Classes are indeed objects as well. That’s why each class has its own singleton class. And each singleton class has its singleton class.

c1.singleton_class.singleton_class.singleton_class.singleton_class
#⇒ #<Class:#<Class:#<Class:#<Class:#<C:0x000055cb0459c700>>>>>

Methods defined on foo are stored in the singleton class of foo. Methods defined on foo’s singleton class are stored in the singleton class of the singleton class of foo. And so forth.

It’s not quite practical, but it’s still possible due to how Ruby treats everything as Object.

Instance variable: self vs @

Writing @age directly accesses the instance variable @age. Writing self.age tells the object to send itself the message age, which will usually return the instance variable @age — but could do any number of other things depending on how the age method is implemented in a given subclass. For example, you might have a MiddleAgedSocialite class that always reports its age 10 years younger than it actually is. Or more practically, a PersistentPerson class might lazily read that data from a persistent store, cache all its persistent data in a hash.

class self idiom in Ruby

First, the class << foo syntax opens up foo's singleton class (eigenclass). This allows you to specialise the behaviour of methods called on that specific object.

a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"

a = 'foo' # new object, new singleton class
a.inspect # => "foo"

Now, to answer the question: class << self opens up self's singleton class, so that methods can be redefined for the current self object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods:

class String
class << self
def value_of obj
obj.to_s
end
end
end

String.value_of 42 # => "42"

This can also be written as a shorthand:

class String
def self.value_of obj
obj.to_s
end
end

Or even shorter:

def String.value_of obj
obj.to_s
end

When inside a function definition, self refers to the object the function is being called with. In this case, class << self opens the singleton class for that object; one use of that is to implement a poor man's state machine:

class StateMachineExample
def process obj
process_hook obj
end

private
def process_state_1 obj
# ...
class << self
alias process_hook process_state_2
end
end

def process_state_2 obj
# ...
class << self
alias process_hook process_state_1
end
end

# Set up initial state
alias process_hook process_state_1
end

So, in the example above, each instance of StateMachineExample has process_hook aliased to process_state_1, but note how in the latter, it can redefine process_hook (for self only, not affecting other StateMachineExample instances) to process_state_2. So, each time a caller calls the process method (which calls the redefinable process_hook), the behaviour changes depending on what state it's in.



Related Topics



Leave a reply



Submit