【发布时间】:2018-12-05 12:20:43
【问题描述】:
我正在阅读 Metaprogramming Ruby 一书,并试图了解如何使用私有方法。它有这样一段:
首先,你需要一个明确的接收者来调用一个对象的方法,而不是 其次,私有方法只能通过隐式接收器调用。
谁能给我一个例子来说明“你需要一个明确的接收者来调用一个不是你自己的对象的方法”?
【问题讨论】:
我正在阅读 Metaprogramming Ruby 一书,并试图了解如何使用私有方法。它有这样一段:
首先,你需要一个明确的接收者来调用一个对象的方法,而不是 其次,私有方法只能通过隐式接收器调用。
谁能给我一个例子来说明“你需要一个明确的接收者来调用一个不是你自己的对象的方法”?
【问题讨论】:
在您引用的文本中,“不是您自己”的意思是与进行调用的上下文(对象)不同。
在这个私有方法的例子中......
class Foo
def bar
baz
end
private
def baz
'hello'
end
end
如果你这样做
Foo.new.baz
您收到一个错误,因为 baz 是使用显式接收器调用的(点之前的部分...Foo.new)
如果你这样做了
Foo.new.bar
=> "hello"
因为方法 bar 在没有接收器的情况下调用 baz,所以这很有效。它能够在没有接收者的情况下调用它,因为bar(如baz)都是Foo 对象的实例方法,因此它们具有相同的上下文(相同的self)。 bar 方法在包含 bar 方法的同一个对象上调用 baz(即“它自己”或“你自己”,如果您在编写对象方法时认为自己坐在对象中)。
现在将类重写为...
class Foo
def bar
self.baz
end
private
def baz
'hello'
end
end
现在您看到bar 不再有效,因为您在方法bar 中调用baz 时将接收器self(一个显式接收器)设为私有。从技术上讲,功能完全相同(没有接收器与接收器相同),但 Ruby 通过禁止显式接收器来实现私有方法,即使是self。因此,如上所述,不能使用显式接收器调用私有方法。
每次你调用一个对象的方法时,你并没有在你自己(即你的上下文)上调用那个方法。
'george'.upcase
=> "GEORGE"
对于upcase,显式接收者是点之前的部分(字符串对象“george”)
如果你这样做了
upcase
没有指定接收者,它假定你想在你的上下文 (self) 中运行 upcase,在 IRB 中是 main:Object。这就是你得到的原因
NameError: undefined lcoal variable or method `upcase' for main:Object
【讨论】:
嗯,基本上你问了两个问题。 显式接收器/隐式接收器取决于您如何调用该方法。 这是一个例子:
class MyClass
def method1
self.method2 # explicit reciever 'self'
method2 # we call the same method but we don't pass a reciever -> implicit reciever
end
def method2
puts "some text in here"
end
end
mc_object = MyClass.new
mc_object.method1 # explicit reciever 'mc'
这段代码将打印“some text in here”两次,一次有显式调用,一次没有。
现在,ruby 中的私有方法是只能在类本身内调用的方法,并且在这样做时您只能使用隐式接收器。 在下一个示例中,我们将添加一个新的私有方法。
class MyClass
def method1
self.method2 # explicit reciever 'self'
method2 # we call the same method but we don't pass a reciever => implicit reciever
method3 # will work - implicit reciever
self.method3 # will not work! - private method `method3' Error
end
def method2
puts "some text in here"
end
private
def method3
puts "this text is private!"
end
end
mc_object = MyClass.new
mc_object.method1 # explicit reciever 'mc'
mc_object.method3 # will not work! - private method `method3' Error
因此您可以看到尝试使用接收器(前缀“self”)访问私有方法会导致错误,并且尝试在类定义之外访问该方法也会导致私有方法错误。
希望对你有帮助:)
【讨论】:
我会回答你的第一个问题:
如何使用私有方法
私有方法最常用于为类提供只能由同一类中的其他方法访问的方法。这些方法仅供类内部使用,不可从外部调用。
【讨论】: