gpt4 book ai didi

ruby-on-rails - 为什么在私有(private)部分中声明委托(delegate)方法时是公开的?

转载 作者:数据小太阳 更新时间:2023-10-29 06:37:02 27 4
gpt4 key购买 nike

我可以通过将声明放在 中使 attr_reader(以及相关的 attr_writerattr_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不要这样工作。这些委托(delegate)方法始终是公共(public)的。

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"

通过将委托(delegate)更改为:

private def_delegator :foo, :b

但我预计上面的 Bar.new.b 会出现 NoMethodError 错误。为什么委托(delegate)不是私有(private)的?

def_delegator(def_instance_delegator 的别名)的方法定义只是rescue(移除 block ):

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 部分中调用的。为什么?

最佳答案

是的,问题出在 module_eval 上,因为它在评估传递的字符串之前明确设置了公共(public)可见性。它在 CRuby 和 JRuby 中的行为方式相同。例如,CRuby 的相关代码在 eval_under 中。功能。

如您所知,当您将 def_delegate 传递给 private 方法时,它会变为私有(private)。 def_delegate 首先将传递的方法定义为 public(通过底层 module_eval),然后通过 private 将其重置为私有(private)可见性。

如果当前 Module.module_eval 的行为是正确的,或者 Forwardable.def_instance_delegator 中存在错误,则不是 100% 清楚。 module_eval 文档中的示例指导在相关类/模块之外使用它,并且它不期望可见性参数,因此将方法的可见性设置为 public 似乎合乎逻辑。

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

关于ruby-on-rails - 为什么在私有(private)部分中声明委托(delegate)方法时是公开的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30339579/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com