在Ruby中声明“私有”/“受保护”时实际发生了什么?

在Ruby类定义中声明private / protected时实际发生了什么? 它们不是关键字 ,因此这意味着它们必须是方法调用,但我无法找到它们的定义位置。 它们似乎没有记录。 声明private / protected方法(如下所示)的两种不同方式是否以不同方式实现? (第二种方式显然是一种方法调用,但这在第一种方式中并不那么明显。)

 class Foo private def i_am_private; end def so_am_i; end end class Foo def i_am_private; end def so_am_i; end private :i_am_private, :so_am_i end 

两者都是方法调用。 引用文档 :

每个function可以以两种不同的方式使用。

  1. 如果不带参数使用,则这三个函数设置后续定义方法的默认访问控制。
  2. 使用参数,函数设置命名方法和常量的访问控制。

请参阅此处的文档

  1. Module.private
  2. 访问控制

您正在寻找Module.private方法如何存在。 这就是发生的地方 。 这里有一些关于它的更多信息 。 您必须从rb_define_private_method定义的class.c开始,阅读更多class.c

希望有所帮助!

我想补充一些类似关键字的行为,因为答案更多的是关于何处而不是如何 ; 答案在于Ruby的复杂元编程function。 可以使用它们作为使用method_added钩子的关键字 ; Ruby中的一个钩子是一个在特定事件(即钩子的名称)出现时调用的函数。 重要的是method_added钩子接收已经定义的方法的名称作为他的参数:这样,就可以修改它的行为。

例如,您可以使用此钩子来定义类似于Python的装饰器的行为; 重要的是,与privateprotected方法不同,这个类似装饰器的方法应该定义一个method_added定义的method_added

 class Module def simple_decorator eigenclass = class << self; self; end eigenclass.class_eval do define_method :method_added do |name| eigenclass.class_eval { remove_method :method_added } old_name = 'old_' + name.to_s alias_method old_name, name class_eval %Q{ def #{name}(*args, &block) p 'Do something before call...' #{old_name}(*args, &block) p '... and something after call.' end } end end end end class UsefulClass simple_decorator def print_something p "I'm a decorated method :)" end def print_something_else p "I'm not decorated :(" end end a = UsefulClass.new a.print_something a.print_something_else 

simple_decorator看起来像一个语言关键字,行为像private ; 但是,因为它删除了method_added钩子,所以它仅适用于紧随其后的方法定义。