What does class << self do in Ruby?

6

6 Answers

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.

6

I found a super simple explanation about class << self , Eigenclass and different type of methods.

In Ruby, there are three types of methods that can be applied to a class:

  1. Instance methods
  2. Singleton methods
  3. Class methods

Instance methods and class methods are almost similar to their homonymous in other programming languages.

class Foo def an_instance_method puts "I am an instance method" end def self.a_class_method puts "I am a class method" end end foo = Foo.new def foo.a_singleton_method puts "I am a singletone method" end 

Another way of accessing an Eigenclass(which includes singleton methods) is with the following syntax (class <<):

foo = Foo.new class << foo def a_singleton_method puts "I am a singleton method" end end 

now you can define a singleton method for self which is the class Foo itself in this context:

class Foo class << self def a_singleton_and_class_method puts "I am a singleton method for self and a class method for Foo" end end end 
2

Usually, instance methods are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.

Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.

If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.

class Zen end z1 = Zen.new z2 = Zen.new class << z1 def say_hello puts "Hello!" end end z1.say_hello # Output: Hello! z2.say_hello # Output: NoMethodError: undefined method `say_hello'… 

In the above example, class << z1 changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.

Classes are also objects (instances of the built-in class called Class). Class methods are nothing more than singleton methods associated with a class object.

class Zabuton class << self def stuff puts "Stuffing zabuton…" end end end 

All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method. IMHO, it's better to use the def self.my_new_clas_method syntax to define class methods, as it makes the code easier to understand. The above example was included so we understand what's happening when we come across the class << self syntax.

Additional info can be found at this post about Ruby Classes.

1

What class << thing does:

class Hi self #=> Hi class << self #same as 'class << Hi' self #=> #<Class:Hi> self == Hi.singleton_class #=> true end end 

[it makes self == thing.singleton_class in the context of its block].


What is thing.singleton_class?

hi = String.new def hi.a end hi.class.instance_methods.include? :a #=> false hi.singleton_class.instance_methods.include? :a #=> true 

hi object inherits its #methods from its #singleton_class.instance_methods and then from its #class.instance_methods.
Here we gave hi's singleton class instance method :a. It could have been done with class << hi instead.
hi's #singleton_class has all instance methods hi's #class has, and possibly some more (:a here).

[instance methods of thing's #class and #singleton_class can be applied directly to thing. when ruby sees thing.a, it first looks for :a method definition in thing.singleton_class.instance_methods and then in thing.class.instance_methods]


By the way - they call object's singleton class == metaclass == eigenclass.

А singleton method is a method that is defined only for a single object.

Example:

class SomeClass class << self def test end end end test_obj = SomeClass.new def test_obj.test_2 end class << test_obj def test_3 end end puts "Singleton's methods of SomeClass" puts SomeClass.singleton_methods puts '------------------------------------------' puts "Singleton's methods of test_obj" puts test_obj.singleton_methods 

Singleton's methods of SomeClass

test


Singleton's methods of test_obj

test_2

test_3

In fact if you write any C extensions for your Ruby projects there is really only one way to define a Module method.

rb_define_singleton_method 

I know this self business just opens up all kinds of other questions so you could do better by searching each part.

Objects first.

foo = Object.new 

Can I make a method for foo?

Sure

def foo.hello 'hello' end 

What do I do with it?

foo.hello ==>"hello" 

Just another object.

foo.methods 

You get all the Object methods plus your new one.

def foo.self self end foo.self 

Just the foo Object.

Try to see what happens if you make foo from other Objects like Class and Module. The examples from all the answers are nice to play with but you have to work with different ideas or concepts to really understand what is going on with the way the code is written. So now you have lots of terms to go look at.

Singleton, Class, Module, self, Object, and Eigenclass was brought up but Ruby doesn't name Object Models that way. It's more like Metaclass. Richard or __why shows you the idea here. And if the blows you away then try looking up Ruby Object Model in search. Two videos that I know of on YouTube are Dave Thomas and Peter Cooper. They try to explain that concept too. It took Dave a long time to get it so don't worry. I'm still working on it too. Why else would I be here? Thanks for your question. Also take a look at the standard library. It has a Singleton Module just as an FYI.

This is pretty good.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy