class Example
private
def example_test
puts 'Hello'
end
end
e = Example.new
e.example_test
这当然不会起作用,因为我们指定了显式接收器 - 示例(e
)的实例,这是针对“私有规则”的。
但我无法理解,为什么人们不能在Ruby中做到这一点:
class Foo
def public_m
self.private_m # <=
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
public_m
方法定义中的当前对象(即self
)是Foo的实例。那么为什么不允许呢?要解决此问题,我必须将self.private_m
更改为private_m
。但为什么这有所不同,self
内的public_m
Foo实例不是?谁是明字private_m
电话的接收者?不是那个self
- 实际上你省略了什么,因为Ruby会为你做这件事(会自己调用private_m)?
我希望我没有太多混淆,我仍然对Ruby感到新鲜。
编辑:
谢谢你的所有答案。将它们放在一起我能够(最终)理解显而易见的事情(对于从未见过像Ruby这样的人来说并不那么明显):self
本身可以是
显性和隐性接收器,并有所作为。因此,如果要调用私有方法,则有两个规则:self
必须是隐式接收器,并且self必须是当前类的实例(在这种情况下为Example
- 并且仅发生当self在实例方法定义内部时,在此方法执行期间)。如果我错了,请纠正我。
class Example
# self as an explicit receiver (will throw an error)
def explicit
self.some_private_method
end
# self as an implicit receiver (will be ok)
def implicit
some_private_method
end
private
def some_private_method; end
end
Example.new.implicit
在google trail中可以找到此问题的任何人的消息:这可能会有所帮助 - http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby
答案 0 :(得分:50)
这是短期和长期的。 Ruby中的私有方法是不能使用显式接收器调用方法,例如some_instance.private_method(值)。因此,即使隐式接收器是self,在您的示例中,您明确使用self,因此无法访问私有方法。
以这种方式思考,您是否希望能够使用已分配给类实例的变量调用私有方法?不。自我是一个变量,所以它必须遵循相同的规则。但是,当您只是在实例中调用该方法时,它会按预期工作,因为您没有明确声明接收器。
Ruby实际上可以使用instance_eval调用私有方法:
class Foo
private
def bar(value)
puts "value = #{value}"
end
end
f = Foo.new
begin
f.bar("This won't work")
rescue Exception=>e
puts "That didn't work: #{e}"
end
f.instance_eval{ bar("But this does") }
希望更清楚一点。
- 编辑 -
我假设你知道这会奏效:
class Foo
def public_m
private_m # Removed self.
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
答案 1 :(得分:17)
Ruby中private
的定义是“只能在没有显式接收器的情况下调用”。这就是为什么你只能在没有显式接收器的情况下调用私有方法。没有其他解释。
请注意,规则实际上有一个例外:由于局部变量和方法调用之间的模糊性,以下总是被解析为对局部变量的赋值:
foo = :bar
那么,如果你想调用名为foo=
的作家,你会怎么做?好吧,你有来添加一个显式接收器,因为没有接收器,Ruby根本就不知道你想要调用方法foo=
而不是分配给局部变量{{1} }:
foo
但是如果你想叫一个名为self.foo = :bar
的{{1}}作家,你会怎么做?您无法写private
,因为foo=
是self.foo =
,因此无法使用显式接收器进行调用。好吧,实际上对于这个特定情况(以及本案例单独),你可以实际使用foo=
的显式接收者来调用一个private
作家。
答案 2 :(得分:13)
这很奇怪,但Ruby的可见性修饰符很多东西都很奇怪。即使self
是隐式接收器,实际拼写它也会使它在Ruby运行时的眼睛中显而易见。当它说私有方法无法使用显式接收器调用时,这意味着它,即使self
计数。
答案 3 :(得分:3)
IIRC,私有方法只允许 隐式接收器(当然,它总是自己的)。
答案 4 :(得分:1)
对不起我的prevoius回答。我只是不明白你的问题。
我改变了你的代码:
class Foo
def public_m
private_m # <=
end
def Foo.static_m
puts "static"
end
def self.static2_m
puts "static 2"
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
Foo.static_m
Foo.static2_m
以下是实例方法的调用:
def public_m
private_m # <=
end
以下是类方法的调用:
def Foo.static_m
puts "static"
end
def self.static2_m
puts "static 2"
end
Foo.static_m
Foo.static2_m
答案 5 :(得分:1)
为User Gates解决方案添加一些增强功能。将私有方法调用到类方法或实例方法几乎是可能的。这是Code Snippets。但不推荐。
类方法
class Example
def public_m
Example.new.send(:private_m)
end
private
def private_m
puts 'Hello'
end
end
e = Example.new.public_m
实例方法
class Example
def self.public_m
Example.new.send(:private_m)
end
private
def private_m
puts 'Hello'
end
end
e = Example.public_m
答案 6 :(得分:0)
没有完全回答问题,但您可以通过这种方式调用私有方法
class Example
private
def example_test
puts 'Hello'
end
end
e = Example.new
e.send(:example_test)