1

次のコードが機能します。

class MyClass
  def method_a
    method_b
  end

  private
  def method_b
    puts "Hello!"
  end
end

m = MyClass.new
m.method_a

ただし、me​​thod_bの呼び出しをに変更してもself.method_b機能しません。

def method_a
  self.method_b
end

取得しNoMethodErrorます。selfインスタンスメソッド内でクラスのインスタンスに解決されるという印象を受けています。なぜself.method_b問題が発生するのですか?

注:がに変更されself.method_bた場合に機能します。privateprotected

注:上記のメソッドがクラスメソッドに変更された場合、self.method_bmethod_aから呼び出しても。はスローされませんNoMethodError

4

2 に答える 2

4

This is how private methods work in Ruby. They cannot be called with an explicit receiver (unless it is a setter method; see below).

Read more in the section on Access Control from the Pickaxe.

Private methods whose names end with an = may be invoked using self.method_name = ... as this is necessary to differentiate them from setting a local variable:

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

That's just how Ruby works: when you provide an explicit object reference, NoMethodError is raised to show the code is breaking intent. You could do a self.send and it would work.

Without the explicit reference, Ruby doesn't do the same visibility check; see this and/or this for a bit more detail.

Nutshell is that private methods can't be called with an explicit receiver, even if it's self.

于 2011-11-29T22:48:28.713 に答える