1

以下代码有效:

class MyClass
  def method_a
    method_b
  end

  private
  def method_b
    puts "Hello!"
  end
end

m = MyClass.new
m.method_a

然而,将对 method_b 的调用更改为self.method_b不起作用:

def method_a
  self.method_b
end

我得到一个NoMethodError. 我的印象是self在实例方法中只解析为类的实例。为什么会self.method_b导致问题?

注意:更改为self.method_b时有效。privateprotected

注意:如果将上述方法更改为类方法self.method_b,则从 method_a 调用不会抛出NoMethodError.

4

2 回答 2

4

这就是private方法在 Ruby 中的工作方式。它们不能用显式接收器调用(除非它是一个 setter 方法;见下文)

在 Pickaxe的访问控制部分中阅读更多信息。

= 可以调用名称以 an 结尾的私有方法,self.method_name = ...因为这是将它们与设置局部变量区分开来的必要条件:

class Foo
  def try
    set_foo(1)            # Invokes private method
    self.set_foo(2)       # ERROR: private method `set_foo' called for ...
    self.send(:set_foo,3) # Invokes private method

    bar = 1               # Sets local variable
    self.bar = 2          # Invokes private method
    self.send(:bar=,3)    # Invokes private method
  end

  private
    def set_foo(v)
      @foo = v
    end
    def bar=(v)
      @bar = v
    end
end

Foo.new.bar = 42          # ERROR: private method `bar=' called for ...
于 2011-11-29T22:48:52.047 回答
3

这就是 Ruby 的工作方式:当您提供显式对象引用时,NoMethodError会引发以显示代码正在破坏意图。你可以做一个self.send,它会工作。

如果没有显式引用,Ruby 不会进行同样的可见性检查;有关更多详细信息,请参阅和/或此。

简而言之,私有方法不能用显式接收器调用,即使它是self.

于 2011-11-29T22:48:28.713 回答