8

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

2 回答 2

9

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

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

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

请参阅此处的文档:

  1. 模块.private
  2. 访问控制

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

希望有帮助!

于 2011-11-05T20:24:43.333 回答
0

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

例如,你可以使用这个钩子来定义类似于 Python 的装饰器的行为;重要的部分是,与privateandprotected方法不同,这种类似装饰器的方法应该定义一个method_added未定义自身的 a:

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钩子,所以它只适用于紧随其后的方法定义。

于 2012-05-02T15:18:47.333 回答