为什么可以在 Ruby 中显式调用私有 class 方法?

Why can a private class method be explicitly invoked in Ruby?

正如我们所知,在 ruby 中不能使用显式接收者调用私有方法。但是当我定义一个 class 时,我可以通过 class 本身调用一个私有的 class 方法。

例如:

class A
   private
     def self.test
        puts "hello,world!"
     end
end

A.test => hello,world!
A.new.test NoMethodError: private method `test' called for #<A:0x007f80b91a10f8>

这与私有的定义相矛盾。谁能告诉我原因。提前致谢!

def self.test 声明了一个 class 方法 ,而不是实例方法。要使 class 方法私有,您需要使用 private_class_method,而不是 private

private 只影响实例方法。要创建私有 class 方法,请使用 private_class_method:

class A
   private_class_method def self.test
      puts "hello,world!"
   end
end

class A
   def self.test
      puts "hello,world!"
   end
   private_class_method :test
end

编辑: 另一种方法是在 metaclass 上定义方法 - 它们将表现为 class 方法。

class A
  class << self
    private
    def test
      puts "hello,world!"
    end
  end
end

不幸的是,没有 protected_class_method 这样的东西 - 但最后一个选项给了我们如何做的提示:

class A
  class << self
    protected
    def test
      puts "hello,world!"
    end
  end
end

但请注意,它只能从后代 class 的 class 方法中调用:

class B < A
  def self.test_class
    A.test
  end
  def test_instance
    A.test
  end
end

B.test_class
# => hello,world!
B.new.test_instance
# => `test_instance': protected method `test' called for A:Class (NoMethodError)