What actually occurs when stating “private”/“protected” in Ruby?

谁说胖子不能爱 提交于 2019-12-12 08:49:11

问题


What is actually occurring when private/protected is stated within a Ruby class definition? They are not keywords, so that implies they must be method calls, but I cannot find where they are defined. They do not appear to be documented. Are the two different ways of declaring private/protected methods (shown below) implemented differently? (The second way is obviously a method call, but this is not so apparent in the first way.)

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

回答1:


Both are method calls. Quoting from docs:

Each function can be used in two different ways.

  1. If used with no arguments, the three functions set the default access control of subsequently defined methods.
  2. With arguments, the functions set the access control of the named methods and constants.

See documentation here:

  1. Module.private
  2. Access Control

You were looking for how the Module.private method comes into existence. Here is where that happens. And here is some more information about it. You would have to read more into it, starting from rb_define_private_method defined in class.c.

Hope that helps!




回答2:


I'd like to add something about their keyword-like behavior, because the answers have been more about where than how; the answer lies in the complex metaprogramming capabilities of Ruby. It is possible to use them as keywords making use of the method_added hook; an hook in Ruby is a function that is called when a specific event (i.e. the hook's name) occurs. What's important is that the method_added hook receives as his argument the name of the method that has been defined: this way, it's possible to modify it's behavior.

For example, you could use this hook to define a behavior similar to Python's decorators; the important part is that, differently from the private and protected methods, this decorator-like method should define a method_added that undefines itself:

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 looks like a language keyword and behaves like private; however, because it removes the method_added hook, it only applies to the immediately following method definition.



来源:https://stackoverflow.com/questions/8022986/what-actually-occurs-when-stating-private-protected-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!