Ruby 中的私有方法和受保护方法

发布于 2024-12-18 11:02:22 字数 582 浏览 2 评论 0原文

以下代码有效:

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 会导致问题?

注意:当 private 更改为 时,self.method_b 可以工作受保护。

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

The following code works:

class MyClass
  def method_a
    method_b
  end

  private
  def method_b
    puts "Hello!"
  end
end

m = MyClass.new
m.method_a

Changing the call to method_b to self.method_b however does not work:

def method_a
  self.method_b
end

I get a NoMethodError. I'm under the impression that self just resolves to the instance of the class when inside an instance method. Why does self.method_b cause problems?

Note: self.method_b works when private is changed to protected.

Note: if the above methods are changed to class methods then calling self.method_b from method_a doesn't throw the NoMethodError.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽清梦 2024-12-25 11:02:22

这就是 Ruby 中私有方法的工作原理。不能使用显式接收器来调用它们(除非它是 setter 方法;见下文)。

请阅读有关 Pickaxe 的访问控制部分了解更多信息。

名称以 = 结尾的私有方法可以使用 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 ...

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 ...
謌踐踏愛綪 2024-12-25 11:02:22

这就是 Ruby 的工作原理:当您提供显式对象引用时,会引发 NoMethodError 以表明代码违反了意图。你可以做一个self.send并且它会起作用。

如果没有显式引用,Ruby 就不会执行相同的可见性检查;请参阅和/或 了解更多详细信息。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文