class << self vs self.method with Ruby: what's better?
This Ruby Style Guide tells that is better using self.method_name
instead of class method_name
. But Why?
class TestClass
# bad
class << self
def first_method
# body omitted
end
def second_method_etc
# body omitted
end
end
# good
def self.first_method
# body omitted
end
def self.second_method_etc
# body omitted
end
end
Are there performance issues?
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.
Generally, class << self
is used in metaprogramming to set the class as self for a prolonged period of time. If I'm trying to write 10 methods, I would use it like so:
METHOD_APPENDICES = [1...10]
class << self
METHOD_APPENDICES.each do |n|
define_method("method#{n}") { n }
end
end
This would create 10 methods (method1, method2, method3, etc.) that would just return the number. I would use class << self
for clarity in this case because in metaprogramming self
is crucial. Littering self.
inside there would actually make things less readable.
If you're just defining class methods normally, stick to self.class_method_name
because more people are likely to understand it. No need to bring in meta-syntax unless you expect your audience to understand it.
As noted above, both styles seem to be equivalent, however using class << self
allows one to mark class methods as private
or protected
. For example:
class UsingDefSelf
def self.a; 'public class method'; end
private
def self.b; 'public class method!'; end
end
class UsingSingletonClass
class << self
def a; 'public class method'; end
private
def b; 'private class method'; end
end
end
private
only affects instance methods. Using the singleton class, we are defining instance methods of that class, which turn into class methods of the containing class!
We can also mark class methods as private
with def self
:
class UsingDefSelf
def self.a; 'private class method'; end
def self.b; 'private class method!'; end
private_class_method :a, :b
# In Ruby 2.1 there is an alternative syntax
private_class_method def self.c; 'private class method!'; end
end
But we cannot mark them as protected
, there is no protected_class_method
. (However, since class is the only instance of its singletonclass, private class method and protected class methods are almost the same except their calling syntax is different.)
Also it is less easier than using class << self
to mark private
class methods, since you have to list all method names in private_class_method
or prefix private_class_method
to every private class method definition.