1

我错过了什么吗?

class Circus
  private
  def start
    puts 'And now for something completely different..'
  end
end

对于我的幻灭:

c=Circus.new
c.start               #NoMethodError: private method `start' called
c.method(:start).call #no problem at all
c.send :start        #neither this fails

谁能给我一个为什么 Ruby 中存在私有方法的原因?

4

4 回答 4

11

这么说吧。在 Ruby 中,您可以轻松地将公共方法修补到调用私有方法的类中,所以...为什么 private阻止您的行为?

你似乎认为private方法在某种程度上是一种安全的东西,它们必须在类之外是不可访问的。封装与安全无关,它是一种用于生成干净、可维护的代码的工具。尊重类公开的接口取决于您。如果你真的想找到一种调用私有方法的方法,你会的。Ruby 不能完全强制执行,也不应该强制执行;这将适得其反并且浪费时间。

我的意思是,任何人都可以给我至少一个为什么“私有”甚至存在于 Ruby 中的原因吗?

由于完全相同的原因private存在于任何其他基于 OOP 的语言中封装。真的,你以为只要能找到绕路绕行的办法private,就应该扔掉吗?

于 2013-06-13T13:16:18.693 回答
6

它声明了方法的意图。如果它是私有的,您不应该调用它,并且您应该意识到这样做可能会导致不可预测或不受欢迎的行为。

值得一提的是,这种行为不仅限于 Ruby——也可以通过反射 API 访问 Java 中的私有成员和变量。

于 2013-06-13T13:13:19.417 回答
0

私有方法应该只在同一个实例内部被调用,没有明确的接收者。每当提供显式接收器时,它们都会失败,包括self.some_private_method从同一实例调用。绕过这个通路的能力send是一种非标准的编码实践,应该主要用于维护。

于 2013-06-13T13:29:02.743 回答
0

一旦你开始使用反射,所有的赌注都没有了。这不是 Ruby 独有的,顺便说一下,几乎所有具有反射的语言都有这个问题。

您可以通过使用编码标准和代码审查来缓解这种情况,例如始终使用public_send等。但如果您不喜欢这样,您将需要使用具有适当分层反射系统的语言,例如Newspeak。

于 2013-06-13T13:57:26.287 回答