Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 为什么在私有部分中声明委托方法时是公共的?_Ruby On Rails_Ruby_Delegates_Metaprogramming - Fatal编程技术网

Ruby on rails 为什么在私有部分中声明委托方法时是公共的?

Ruby on rails 为什么在私有部分中声明委托方法时是公共的?,ruby-on-rails,ruby,delegates,metaprogramming,Ruby On Rails,Ruby,Delegates,Metaprogramming,我可以通过将声明放入private部分,使attr\u reader(以及相关的attr\u writer和attr\u accessor)方法私有化: class Foo private attr_reader :b end Foo.new.b # => NoMethodError: private method `b' called for #<Foo:> 通过将委托更改为以下内容,可以轻松地将其私有化: private def_delegator :foo, :b

我可以通过将声明放入
private
部分,使
attr\u reader
(以及相关的
attr\u writer
attr\u accessor
)方法私有化:

class Foo
private
  attr_reader :b
end

Foo.new.b # => NoMethodError: private method `b' called for #<Foo:>
通过将委托更改为以下内容,可以轻松地将其私有化:

private def_delegator :foo, :b
但是我预期上面的
Bar.new.b
会出现
NoMethodError
错误。为什么代表团不是私人的

def_delegator
(def_instance_delegator的别名)的方法定义只是
rescue
(已删除块):


这意味着
module_-eval
不考虑它是在
private
节中调用的。为什么?

是的,问题在于
模块的评估
,因为它在评估传递的字符串之前显式设置了公共可见性。 它在CRuby和JRuby中的行为方式相同。例如,CRuby的有罪代码正在运行

如您所知,当您将
def_delegate
传递给
private
方法时,它将变为private
def_delegate
首先将传递的方法定义为public(由底层模块评估),然后由
private
重置为private visibility

当前的
模块.Module\u eval
行为是否正确,或者
可转发的.def\u实例\u delegator
中是否存在错误,尚不完全清楚
module_eval
documentation guide中的示例在相关类/模块之外使用它,它不需要visibility参数,所以它将方法的可见性设置为公共的似乎是合乎逻辑的

解决方案可能是
Module.Module_eval
处理可选可见性参数,并在发送到隐式或显式
self
时尊重当前可见性(如果可能,请怀疑)或者修复
Forwardable.def_instance_delegator
实现,以使用更合适的
Module.define_method
而不是
Module_eval
来定义方法。
在任何情况下,这都是一个很好的填充错误报告的候选者。

我认为这是应该工作的。我总是认为可见性修饰符影响了它们写入的范围,而不是从那里发出的任何调用。从这个意义上说,对模块的调用并不知道它在一个私有部分内(可以吗?)

第二个选项似乎有效,而第一个选项无效,因为Rails说“模块评估此特定行”。因此,当您在同一行上有private时,它理解应该开始将其视为私有方法定义。这似乎是Rails维护人员应该解决的问题,为他们制造了一个问题

private def_delegator :foo, :b
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