有没有办法从 Ruby 中的实例调用私有类方法?
当然,除了 self.class.send :method, args...
。 我想在类和实例级别提供一个相当复杂的方法,而无需重复代码。
更新:
@Jonathan Branam:这是我的假设,但我想确保没有其他人找到解决方法。 Ruby 中的可见性与 Java 中的可见性有很大不同。 您也说得对, private
不适用于类方法,尽管这将声明一个私有类方法:
class Foo
class <<self
private
def bar
puts 'bar'
end
end
end
Foo.bar
# => NoMethodError: private method 'bar' called for Foo:Class
Other than self.class.send :method, args...
, of course. I'd like to make a rather complex method available at both the class and instance level without duplicating the code.
UPDATE:
@Jonathan Branam: that was my assumption, but I wanted to make sure nobody else had found a way around. Visibility in Ruby is very different from that in Java. You're also quite right that private
doesn't work on class methods, though this will declare a private class method:
class Foo
class <<self
private
def bar
puts 'bar'
end
end
end
Foo.bar
# => NoMethodError: private method 'bar' called for Foo:Class
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这是与问题相关的代码片段。 在类定义中使用“private”不适用于类方法。 您需要使用“private_class_method”,如下例所示。
我看不出有什么办法可以解决这个问题。 文档说你不能指定私有方法的接收。 此外,您只能从同一实例访问私有方法。 类 Foo 是一个与给定的 Foo 实例不同的对象。
不要将我的答案视为最终答案。 我当然不是专家,但我想提供一个代码片段,以便其他尝试回答的人将拥有正确的私有类方法。
Here is a code snippet to go along with the question. Using "private" in a class definition does not apply to class methods. You need to use "private_class_method" as in the following example.
I don't see a way to get around this. The documentation says that you cannot specify the receive of a private method. Also you can only access a private method from the same instance. The class Foo is a different object than a given instance of Foo.
Don't take my answer as final. I'm certainly not an expert, but I wanted to provide a code snippet so that others who attempt to answer will have properly private class methods.
让我为这个或多或少奇怪的解决方案和非解决方案列表做出贡献:
Let me contribute to this list of more or less strange solutions and non-solutions:
现在你不再需要辅助方法了。 您可以简单地将它们内联到您的方法定义中。 对于 Java 人员来说,这应该非常熟悉:
不,您不能从实例方法调用私有类方法。 但是,您可以使用
private_constant< 将 private 类方法实现为 private 嵌套类中的 public 类方法。 /code> 辅助方法。 有关更多详细信息,请参阅此博文。
Nowadays you don't need the helper methods anymore. You can simply inline them with your method definition. This should feel very familiar to the Java folks:
And no, you cannot call a private class method from an instance method. However, you could instead implement the the private class method as public class method in a private nested class instead, using the
private_constant
helper method. See this blogpost for more detail.如果您的方法仅仅是一个实用函数(也就是说,它不依赖在任何实例变量上),您可以将该方法放入模块中,并
包含
和扩展
该类,以便它既可用作私有类方法又可用作私有实例方法。If your method is merely a utility function (that is, it doesn't rely on any instance variables), you could put the method into a module and
include
andextend
the class so that it's available as both a private class method and a private instance method.这是使用“真正的”私有类方法的方法。
干杯
This is the way to play with "real" private class methods.
cheers
这可能是最“原生的 Ruby”方式:
通过一些 Ruby 元编程,您甚至可以使其看起来像:
Ruby 的元编程非常强大,因此您可以在技术上实现您可能想要的任何范围规则。 话虽这么说,我仍然更喜欢第一个变体的清晰度和最小的惊喜。
This is probably the most "native vanilla Ruby" way:
With some Ruby metaprogramming, you could even make it look like:
Ruby's metaprogramming is quite powerful, so you could technically implement any scoping rules you might want. That being said, I'd still prefer the clarity and minimal surprise of the first variant.
前面的例子(不再?)有效。 不能直接调用私有类方法; 即使来自同一个班级。 相反,您需要使用
send
。The prior examples (no longer?) work. You cannot call the private class method directly; even from within the same class. Instead, you need to use
send
.除非我误解了,否则您不需要这样的东西:
当然,如果您想避免对类名进行硬编码,您可以更改第二个定义以使用 self.class.send 方法...
Unless I'm misunderstanding, don't you just need something like this:
Of course you could change the second definition to use your self.class.send approach if you wanted to avoid hardcoding the class name...