Private Class Methods in Ruby
By Chun-wei Kuo onTo make a class method private, the intuitive way is to put private
before the method definition like the following.
class Foo
private
def self.bar
"bar"
end
end
But that does not seem to be sufficient, unfortunately.
The method is still public:
pry(main)> Foo.bar
=> "bar"
Actually, to make it private, we have to call private_class_method
like the
following.
class Foo
def self.bar
"bar"
end
private_class_method :bar
end
We can confirm that it works by calling the class method in a Ruby console.
pry(main)> Foo.bar
NoMethodError: private method `bar' called for Foo:Class
Why is that?
Before we jump into the explanation, please take a look at the following code, which is another way to make a class method private.
class Foo
class << self
private
def bar
"bar"
end
end
end
In the example above, the singleton class is opened and the method bar
is defined as a private instance method on it.
The syntax looks different but it works as same as the previous example.
pry(main)> Foo.bar
NoMethodError: private method `bar' called for Foo:Class
In Ruby, as we know, classes are just objects.
When we define a “class method” on Foo
, we are just defining an
instance method on the singleton class of the Foo
object.
pry(main)> Foo.singleton_class.private_instance_methods(false)
=> [:bar]
And private
is not a special keyword but a method on Module
.
It is available on Class
because Class.is_a? Module
.
When private
gets called, it sets the visibility for subsequently methods
defined on the current object to private.
Therefore, to set the visibility of methods defined on the singleton class of
the current object, we need another method.
That is where Module#private_class_method
comes in.
To summarize, there are two styles of syntax to create a private class method
bar
on a class Foo
.
- Define the method with the syntax
def self.bar
and thenprivate_class_method :bar
to make it private. - Or open the singleton class of
Foo
and define a private method on the singleton class.
p.s. The term “singleton class” referred in this post is also called “metaclass” or “eigenclass”.
Comments