有没有办法从Ruby中的实例调用私有的类方法?
当然不是self.class.send :method, args...
。我希望在类和实例级别都可以使用相当复杂的方法,而无需重复代码。有没有办法从Ruby中的实例调用私有的类方法?
UPDATE:
@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
下面的代码片段与问题走。在类定义中使用“private”不适用于类方法。您需要使用“private_class_method”,如下例所示。
class Foo
def self.private_bar
# Complex logic goes here
puts "hi"
end
private_class_method :private_bar
class <<self
private
def another_private_bar
puts "bar"
end
end
public
def instance_bar
self.class.private_bar
end
def instance_bar2
self.class.another_private_bar
end
end
f=Foo.new
f=instance_bar # NoMethodError: private method `private_bar' called for Foo:Class
f=instance_bar2 # NoMethodError: private method `another_private_bar' called for Foo:Class
我看不出有办法解决这个问题。该文件说,你不能指定接收私人方法。您也只能从同一个实例访问私有方法。 Foo类是与Foo的给定实例不同的对象。
不要把我的答案作为最终答案。我当然不是专家,但我想提供一个代码片段,以便其他尝试回答的人将拥有适当的私有类方法。
除非我误解,你不只是需要这样的:
class Foo
private
def Foo.bar
# Complex logic goes here
puts "hi"
end
public
def bar
Foo.bar
end
end
当然你可以改变使用您的self.class.send方法,如果你想避免硬编码类名称的第二个定义...
如果你的方法仅仅是utility function(也就是说,它不依赖于任何实例变量),你可以把方法变成一个模块,include
和extend
类,以便它可以同时作为私有的类方法和一个私人实例方法。
这是玩“真正的”私人类方法的方式。
class Foo
def self.private_bar
# Complex logic goes here
puts "hi"
end
private_class_method :private_bar
class <<self
private
def another_private_bar
puts "bar"
end
end
public
def instance_bar
self.class.private_bar
end
def instance_bar2
self.class.another_private_bar
end
def calling_private_method
Foo.send :another_private_bar
self.class.send :private_bar
end
end
f=Foo.new
f.send :calling_private_method
# "bar"
# "hi"
Foo.send :another_private_bar
# "bar"
欢呼
让我或多或少奇怪的解决方案和非方案的这个名单贡献:
puts RUBY_VERSION # => 2.1.2
class C
class << self
private def foo
'Je suis foo'
end
end
private define_method :foo, &method(:foo)
def bar
foo
end
end
puts C.new.bar # => Je suis foo
puts C.new.foo # => NoMethodError
现在你不需要辅助方法了。你可以简单地将它们与你的方法定义联系起来。对于Java人来说,这应该是非常熟悉的:
class MyClass
private_class_method def self.my_private_method
puts "private class method"
end
private def my_private_method
puts "private instance method"
end
end
而且,不能从实例方法调用私有类方法。但是,您可以改为实现在私人嵌套类的私人类方法,如公共类方法,而不是使用private_constant
helper方法。有关更多详细信息,请参阅this blogpost。
获取第一个示例的错误:`1.9。3p327:078> F = Foo.new =># 1.9.3p327:079> f.class.send:calling_private_method NoMethodError:未定义的方法\`calling_private_method”的富:从 类(IRB) :79 from〜/ .rvm/rubies/ruby-1.9.3-p327/bin/irb:16:in \''` –
TrinitronX
2013-02-22 21:57:36
是的,这不起作用(或者可能不再有效)。 – 2017-09-01 00:44:57