简体   繁体   中英

How to access private class methods in Ruby?

Given a Class in Ruby:

class MyClass
  def self.my_class_method
    puts "class method"
  end

  private

  def my_method
    puts "regular method"
  end

  private_class_method :my_class_method
end

To access private methods I can call .send(:my_method) on the Class Object, but how does that work for class methods?

You should do:

class MyClass
  def self.my_class_method
    puts "class method"
  end

  private

  def my_method
    puts "regular method"
  end

  private_class_method :my_class_method
end

# to call class method
MyClass.send :my_class_method # => class method
# to call instance method
MyClass.new.send :my_method # => regular method

In Ruby, class(s) are also objects, so you can call the #send method on the class also.

In Ruby, you can define private class methods as

class MyClass
  class << self
    private 

    def my_class_method
      puts "class method"
    end
  end
end

Or using thhis macro like method: private_class_method

Just for reference, that's not how you create a private class method.

class A
  private

  def self.foo
    "foo"
  end
end

A.foo # => "foo"

To create a private class method, you need to use private_class_method .

class A
  def self.foo
    "foo"
  end

  private_class_method :foo
end

A.foo # => private method `foo' called for A:Class

First off, MyClass.send(:my_method) would not work. You have to send it to an instance: MyClass.new.send(:my_method) .

Then, your my_class_method is not really private.
Ruby's semantic of private are somewhat different from what you might be used to in other languages. Since Ruby allows you to bypass encapsulation if you choose to, private just means that a method can only be called implicitly , without sending a message to an actual object.

For example:

class Example
  def test
    'foobar'
  end

  def hello
    puts test        # implicit receiver
    puts self.test   # explicit receiver
  end
end

This is all good, but why is this important for your question?
Because you're declaring my_class_method explicitly on self . Doing so bypasses the private modifier, and the method is public. This means that you can just call it with:

MyClass.my_class_method

If you really need private class methods, then you can define them on the metaclass:

class MyClass

  class << self

    private

    def my_class_method
      puts "class method"
    end
  end


  private

  def my_method
    puts "regular method"
  end

end

This will make my_class_method actually private, and force you to invoke it with any of these:

MyClass.send :my_class_method
MyClass.class_exec { my_class_method }
MyClass.class_eval { my_class_method }
MyClass.class_eval "my_class_method"

There are no such things as class methods. Class methods are just singleton methods of the class. But there are no such things as singleton methods either. Singleton methods are just instance methods of the singleton class. So, class methods are just instance methods of the class's singleton class.

Since there is no such thing as a class method, only instance methods, you already know what to do:

To access private methods I can call .send(:my_method) on the Class Object, but how does that work for class methods?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM