Recently I came across an unusual syntax in Ruby:
class FooBar class << self end end
Today I want to share what I learned about it.
Class Methods vs. Instance Methods
Before we consider the syntax above let us recall when we use class methods. Imagine that we are working with a weather app and there we have a class called City.
As you know, in OOP a City class is kind of a blueprint that is designed to instantiate instances for each specific city. Each instance of a city has information about its name, current temperature, humidity, etc. Instance methods are great in this case and at first look it seems that only class instances are needed and each operation should use instance methods. Can there be any case when we would need class methods?
[ Note: in Java, C# and few other languages class methods are called static methods ]
But how can we decide whether we need to use class methods or instances and instance methods?
The basic rule is asking whether we could call a method even if we did not have an instance of a class. There are many cases where this can be done and can be very useful.
For example, in the case of the City class, we can always convert temperature from Fahrenheit to Celsius or vice versa. We don’t really care for which city we are converting these values too. Equally, we could convert feet to meters on a current visibility method. Also, consider a user making a query about the weather in a specific city in which we query the database. Again, we don’t need to have any instance of the class. We can just do a database query to the city’s name.
And there are many other cases when using class methods makes sense. At the same time, if we need to update current weather condition values for a specific city class methods do not seem appropriate. In such a case, we’d be working on an instance of the City class for a specific city.
So as a general rule, class methods are used when we need some utility methods or in database queries in which the method does not depend on information scoped to a specific instance.
With few exceptions, in Ruby basic instance methods are written as:
def some_instance_method # body omitted end
However, there are several ways of writing class methods in Ruby. The most common syntax for class methods is:
def self.some_class_method # body omitted end
This style is documented in “Defining Class Methods” in Rubocop’s Ruby Style Guide.
In the above-recommended syntax ‘self’ obviously means current class itself - as everything is an object in Ruby (that is, an instance of class Class) ‘self’ refers to the object pointing to the City class in our example.
Another way of writing class methods is:
def City.some_class_method # body omitted end
This syntax is discouraged by The Ruby Style Guide and should be avoided since, if for some reason, the class name changes, all class method definitions will point to an undefined class. Therefore using ‘self’ makes refactoring easier.
But what if we define multiple class methods within a class? Then we still could use the syntax defined above.
Conveniently, Ruby offers another syntax that enables defining a class methods block:
class City class << self def fahrenheit_to_celsius # body omitted end def feet_to_meters # body omitted end def find(city) # body omitted end end def some_instance_method # body omitted end def another_instance_method # body omitted end end
Here the three methods defined inside of the class method block are class methods and the two methods defined outside are instance methods.
Which of the three methods is preferred? As discussed, the syntax discouraged by The Ruby Style Guide should be avoided for the previously stated reasons.
When it comes to defining class methods separately or using the class methods block approach many developers agree that there is no preferred approach. However, it should be noted that using the class method block syntax helps with code organization, clearly separating class methods from instance methods. Regardless, consistency is key, as throughout any particular codebase, in aiding readability and, to a lesser extent, maintainability.
Despite unusual syntax, class « self simply means that it is a start of class methods block. Class methods are just like any other method, but they can be called on the class without initializing an instance of this class.
What is next? We can also use singletons in a similar way we discussed above:
class City city = Object.new class << city def fahrenheit_to_celsius # body omitted end end def some_instance_method # body omitted end end
Singletons and how methods are used with singletons is a bigger topic. I will examine it in more detail in one of our future blog posts.