简体   繁体   English

如何在Ruby中访问私有类方法?

[英]How to access private class methods in Ruby?

Given a Class in Ruby: 给出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? 要访问私有方法,我可以在类对象上调用.send(:my_method) ,但是这对于类方法有什么用呢?

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. 在Ruby中,类也是对象,因此您也可以在类上调用#send方法。

In Ruby, you can define private class methods as 在Ruby中,您可以将私有类方法定义为

class MyClass
  class << self
    private 

    def my_class_method
      puts "class method"
    end
  end
end

Or using thhis macro like method: private_class_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 . 要创建私有类方法,需要使用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. 首先, MyClass.send(:my_method)不起作用。 You have to send it to an instance: MyClass.new.send(:my_method) . 您必须将它发送到一个实例: MyClass.new.send(:my_method)

Then, your my_class_method is not really private. 然后,你的my_class_method不是真的私有。
Ruby's semantic of private are somewhat different from what you might be used to in other languages. Ruby的private语义与您在其他语言中的习惯有所不同。 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. 由于Ruby允许您在选择时绕过封装,因此private只意味着只能隐式调用方法,而不向实际对象发送消息。

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 . 因为你宣布my_class_method上明确self Doing so bypasses the private modifier, and the method is public. 这样做会绕过 private修饰符,并且该方法是公共的。 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: 如果你真的需要private类方法,那么你可以在元类上定义它们:

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: 这将使my_class_method 实际上是私有的,并强制您使用以下任何一个来调用它:

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? 要访问私有方法,我可以在类对象上调用.send(:my_method) ,但是这对于类方法有什么用呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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