Частные и защищенные методы в Ruby

Следующий код работает:

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 работает когда private изменено на protected,

Примечание: если вышеприведенные методы изменены на методы класса, то вызов self.method_b из method_a не выбрасывает NoMethodError,

2 ответа

Решение

Вот как private методы работают в Ruby. Они не могут быть вызваны с явным получателем (если это не метод установки; см. Ниже).

Подробнее читайте в разделе " Контроль доступа от кирки".

Частные методы, имена которых заканчиваются на = может быть вызван с помощью 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 ...

Вот как работает Ruby: когда вы предоставляете явную ссылку на объект, NoMethodError поднимается, чтобы показать, что код нарушает намерение. Вы могли бы сделать self.send и это будет работать.

Без явной ссылки Ruby не выполняет ту же проверку видимости; посмотрите это и / или это для более подробной информации.

В двух словах: частные методы нельзя вызывать с явным получателем, даже если self,

Другие вопросы по тегам