问题
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.
- If used with no arguments, the three functions set the default access control of subsequently defined methods.
- With arguments, the functions set the access control of the named methods and constants.
See documentation here:
- Module.private
- 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