Ruby方法instance_eval()和send()是否否定了私有可见性的好处?

pez*_*ser 2 ruby visibility access-specifier

w = Widget.new # Create a Widget
w.send :utility_method # Invoke private method!
w.instance_eval { utility_method } # Another way to invoke it
w.instance_eval { @x } # Read instance variable of w
Run Code Online (Sandbox Code Playgroud)

查看上面与Widget类(下面)相关的示例,send和instance_eval方法违反了私有和受保护可见性提供的所有保护.如果是这样,为什么要在Ruby中使用私有和受保护的访问权限,因为无法保证您的定义能够得到尊重?

class Widget
  def x # Accessor method for @x
   @x
  end
  protected :x # Make it protected
  def utility_method # Define a method
   nil
  end
  private :utility_method # And make it private
end
Run Code Online (Sandbox Code Playgroud)

Mar*_*llo 12

红宝石相信赋予你做你想做的事的力量.它只是不容易无意中射击你的脚 - 如果你想颠覆私人声明,你必须使用语法,明确你这样做.请注意,最终决定代码应该或不应该做的人是使用库的人,而不是编写它的人.


Ska*_*ade 5

我无法评论,因为低代表:/.

重新定义发送是没有用的,因为发送仅仅是为了共同的名字__send__(这就是下划线,下划线,"发送",下划线,下划线),这实际上是实现信息发送的方法.不建议重新定义任何__method__.另外,另一个人也可以重新打开该类并恢复定义:

class Widget
  def send(method, *args, &block)
    super
  end
  #and so on
end
Run Code Online (Sandbox Code Playgroud)

在Ruby 1.9中,行为略有不同:#send实际上是为了尊重可见性,而__send__则没有.

Ruby中的private有更多的声明性目的:声明为private的方法是一个实现细节而不是API细节.您不得意外地从外部发送消息.但是,如果他们认为合适,任何人仍然可以强行规避这种限制 - 在他们自己的帐户上.