Я могу сделать attr_reader
(и связанные с ним attr_writer
и attr_accessor
) методы private, поместив объявление в раздел private
:
class Foo
private
attr_reader :b
end
Foo.new.b # => NoMethodError: private method `b' called for #<Foo:>
Однако Rails delegate
и стандартная библиотека Ruby def_delegate
не работают таким образом. Эти делегированные методы всегда общедоступны.
class Foo
attr_reader :b
def initialize
@b = 'b'
end
end
require 'forwardable'
class Bar
attr_reader :foo
def initialize
@foo = Foo.new
end
extend Forwardable
private
def_delegator :foo, :b
end
Bar.new.b # => "b"
Сделать делегирование приватным легко, изменив его на:
private def_delegator :foo, :b
но я ожидал ошибку NoMethodError
для Bar.new.b
выше. Почему делегация не является частной?
Определение метода def_delegator
(псевдоним для def_instance_delegator
) - это просто rescue
(удалены блоки):
def def_instance_delegator(accessor, method, ali = method)
line_no = __LINE__; str = %Q{
def #{ali}(*args, &block)
#{accessor}.__send__(:#{method}, *args, &block)
end
}
module_eval(str, __FILE__, line_no)
end
Это означает, что module_eval
не считает, что он был вызван в разделе private
. Почему?