ruby-on-rails – 为什么在私有版本中声明一个委派方法是公开的
我可以通过将声明放在私人部分中来使attr_reader(以及相关的attr_writer和attr_accessor)方法是私有的:
class Foo private attr_reader :b end Foo.new.b # => NoMethodError: private method `b' called for #<Foo:> 但是,Rails的 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 但是我预计上面的Bar.new.b会出现一个NoMethodError错误.为什么代表团不是私人的? def_delegator(def_instance_delegator的别名)的方法定义只是拯救(已移除块): 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不尊重它在私有部分中被调用.为什么? 解决方法
是的,问题是使用module_eval,因为它在评估传递的字符串之前显式设置公共可见性.
它在CRuby和JRuby中的行为方式相同.例如,CRuby的被证明的代码是 eval_under的功能. 如你所知,当您将def_delegate传递给私有方法时,它将变为私有的. def_delegate首先将传递的方法定义为public(由底层的module_eval),然后通过private重置为私有可见性. 如果当前Module.module_eval的行为是正确的或者在Forwardable.def_instance_delegator中存在错误,那么这不是100%清楚.在文档指南中使用module_eval示例将其用于相关类/模块之外,并且不期望可见性参数,因此将方法的可见性设置为public似乎是合乎逻辑的. 解决方案将是Module.module_eval处理可选可见性参数,并在发送到隐式或显式自身时尊重当前可见性(如果可能的话怀疑)或修复Forwardable.def_instance_delegator实现来定义具有更合适的Module.define_method而不是module_eval的方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |