Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

private and private_class_method keywords in Ruby

Tags:

ruby

Why does private is applicable only for instance methods and isn't for the class methods? Not only that, why doesn't private_class_method method make the class methods private?

class Foo

  private

  def self.private_class_method
    puts 'hello from private_class_method'
  end


  def private_instace_method
    puts 'hello from private_instace_method'
  end
end

Foo.private_class_method #Ok!
Foo.new.private_instace_method #error: private method `private_instace_method' called for #<Foo:0x000001020873b8>

How about this?

class Foo

  private_class_method :private_class_method

  def self.private_class_method
    puts 'hello from private_class_method'
  end

  private

  def private_instace_method
    puts 'hello from private_instace_method'
  end
end

Foo.private_class_method #Ok!
Foo.new.private_instace_method #error: private method `private_instace_method' called for #<Foo:0x000001020873b8>

How do I make a class method private?

like image 969
Incerteza Avatar asked May 06 '26 01:05

Incerteza


2 Answers

You can create a private class methods like this:

class Foo
  def self.will_be_private
    # ...
  end
  private_class_method :will_be_private
end

Or like this:

class Foo
  class << self
  private
    def will_be_private
      # ...
    end
  end
end 

While it is possible the make a class methods private, I can hardly think of a good reason to do so. IMO a private class method is a code smell and indicates that there is a thing that should be extracted into it own class.

like image 79
spickermann Avatar answered May 08 '26 16:05

spickermann


Why does private is applicable only for instance methods and isn't for the class methods?

This part of the OP never got answered, and I thought it deserved to be, not least since I had the same question.

The short answer is that the private keyword is actually a method call on the instance’s class which sets the visibility for subsequently defined instance methods; unlike what it seems on first look, it's not a language keyword meaning "make everything after this point private".

More detail...

When you're defining a class method, you typically do it like this...

class SomeClass
    def self.some_class_method
      # ...
    end
end

That self. part means that you're defining a method not on instances of the class, but on self, which is the "singleton class" for (in this case) SomeClass. Calling private affects instance methods since they're attached to the instance itself, but class methods are attached somewhere else - to the singleton class -, so aren't affected by it. By contrast, private_class_method calls set_method_visibility(rb_singleton_class(obj) so is explicitly concerned with the singleton class methods.

I found this article helpful: https://jakeyesbeck.com/2015/08/23/ruby-objects/.

Don't worry if you find this confusing - you're not the only one! I recommend experimenting with these concepts in irb to help.

like image 31
Sam Avatar answered May 08 '26 16:05

Sam



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!