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

时间:2011-11-05 20:17:40

标签: ruby access-specifier

在Ruby类定义中声明private / protected时实际发生了什么?它们不是keywords,因此这意味着它们必须是方法调用,但我无法找到它们的定义位置。它们似乎没有记录。声明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

2 个答案:

答案 0 :(得分:9)

两者都是方法调用。引自docs

  

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

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

请参阅此处的文档:

  1. Module.private
  2. Access Control
  3. 您正在寻找Module.private方法的存在方式。 Here is where that happens。关于它,here is some more information。从rb_define_private_method中定义的class.c开始,您需要阅读更多内容。

    希望有所帮助!

答案 1 :(得分:0)

我想添加一些关于类关键字行为的内容,因为答案更多地是关于 where 而不是如何;答案在于Ruby的复杂元编程功能。 可以使用{em>关键字来使用method_added钩子; Ruby中的钩子是在发生特定事件(即钩子的名称)时调用的函数。 重要的是method_added挂钩作为参数接收已定义方法的名称:这样,就可以修改它的行为。

例如,您可以使用此钩子来定义类似于Python的装饰器的行为;重要的是,与privateprotected方法不同,这种类似装饰器的方法应该定义一个取消定义自己的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挂钩,它只适用于紧接着的方法定义。