[英]What does `&method(:method_ name)` mean in ruby?
I was trying to create a class that has a private class method. 我试图创建一个具有私有类方法的类。 I want this private class method available to be used inside an instance method.
我希望这个私有类方法可用于实例方法。
The following was my first attempt: 以下是我的第一次尝试:
class Animal
class << self
def public_class_greeter(name)
private_class_greeter(name)
end
private
def private_class_greeter(name)
puts "#{name} greets private class method"
end
end
def public_instance_greeter(name)
self.class.private_class_greeter(name)
end
end
Animal.public_class_greeter('John')
works fine, printing John greets private class method
. Animal.public_class_greeter('John')
工作正常,打印John greets private class method
。
However, Animal.new.public_instance_greeter("John")
throws an error: NoMethodError: private method 'private_class_greeter' called for Animal:Class
. 但是,
Animal.new.public_instance_greeter("John")
抛出一个错误: NoMethodError: private method 'private_class_greeter' called for Animal:Class
。
That is expected, as the invocation self.class.private_class_greeter
is same as Animal.private_class_greeter
, which obviously throws an error. 这是预期的,因为调用
self.class.private_class_greeter
与Animal.private_class_greeter
相同,这显然会引发错误。
After searching on how this can be fixed, I came up with the following code, that does the job: 在搜索了如何解决这个问题之后,我想出了以下代码:
class Animal
class << self
def public_class_greeter(name)
private_class_greeter(name)
end
private
def private_class_greeter(name)
puts "#{name} greets private class method"
end
end
define_method :public_instance_greeter, &method(:private_class_greeter)
end
I don't exactly understand what is happening here: &method(:private_class_greeter)
. 我不完全理解这里发生了什么:
&method(:private_class_greeter)
。
Could you please explain what does this mean? 你能解释一下这是什么意思吗?
If I were to replace: 如果我要替换:
define_method :public_instance_greeter, &method(:private_class_greeter)
with: 有:
def public_instance_greeter
XYZ
end
then, what should be the content in place of XYZ
? 那么,代替
XYZ
的内容应该是什么?
How does Ruby parse &method(:private_class_greeter)
? Ruby解析
&method(:private_class_greeter)
如何?
The expression &method(:private_class_greeter)
is 表达式
&method(:private_class_greeter)
是
method(:private_class_greeter)
method(:private_class_greeter)
的值method(:private_class_greeter)
&
operator. &
运算符为前缀。 What does the method
method do? method
方法有什么作用?
The method
method looks up the specified method name in the current context and returns a Method
object that represents it. method
方法在当前上下文中查找指定的方法名称,并返回表示它的Method
对象。 Example in irb
: irb
示例:
def foo
"bar"
end
my_method = method(:foo)
#=> #<Method: Object#foo>
Once you have this method, you can do various things with it: 拥有此方法后,您可以使用它执行各种操作:
my_method.call
#=> "bar"
my_method.source_location # gives you the file and line the method was defined on
#=> ["(irb)", 5]
# etc.
What is the &
operator for? 什么是
&
运营商?
The &
operator is used to pass a Proc
as a block to a method that expects a block to be passed to it. &
运算符用于将Proc
作为块传递给期望将块传递给它的方法。 It also implicitly calls the to_proc
method on the value you pass in, in order to convert values that are not Proc
into a Proc
. 它还隐式调用传入的值的
to_proc
方法,以便将非Proc
值转换为Proc
。
The Method
class implements to_proc
— it returns the contents of the method as a Proc
. Method
类实现to_proc
- 它将方法的内容作为Proc
。 Therefore, you can prefix a Method
instance with &
and pass it as a block to another method: 因此,您可以使用
&
作为Method
实例的前缀,并将其作为块传递给另一个方法:
def call_block
yield
end
call_block &my_method # same as `call_block &my_method.to_proc`
#=> "bar"
The define_method
method just happens to take a block with the contents of the new method that is being defined. define_method
方法恰好采用了正在定义的新方法的内容的块。 In your example, &method(:private_class_greeter)
passes in the existing private_class_greeter
method as a block. 在您的示例中,
&method(:private_class_greeter)
将现有的private_class_greeter
方法作为块传递。
Is this how &:symbol
works? 这是
&:symbol
工作原理吗?
Yes. 是。
Symbol
implements to_proc
so that you can simplify your code like this: Symbol
实现to_proc
以便您可以像这样简化代码:
["foo", "bar"].map(&:upcase)
#=> ["FOO", "BAR"]
# this is equivalent to:
["foo", "bar"].map { |item| item.upcase }
# because
:upcase.to_proc
# returns this proc:
Proc { |val| val.send(:upcase) }
How can I replicate &method(:private_class_greeter)
? 我怎样才能复制
&method(:private_class_greeter)
?
You can pass in a block that calls the target method: 您可以传入一个调用目标方法的块:
define_method :public_instance_greeter do |name|
self.class.send(:private_class_greeter, name)
end
Of course, then you don't need to use define_method
anymore, which results in the same solution Eric mentioned in his answer : 当然,那么你不再需要使用
define_method
,这导致了Eric在他的回答中提到的相同解决方案:
def public_instance_greeter(name)
self.class.send(:private_class_greeter, name)
end
First, take good care with your indentation. 首先,要小心你的缩进。
private
should be 2 spaces to the right: it gives the impression that public_instance_greeter
is private otherwise. private
应该是右边的2个空格:它给人的印象是public_instance_greeter
是私有的。
If you don't care about encapsulation, you could simply use Kernel#send
: 如果你不关心封装,你可以简单地使用
Kernel#send
:
class Animal
class << self
def public_class_greeter(name)
private_class_greeter(name)
end
private
def private_class_greeter(name)
puts "#{name} greets private class method"
end
end
def public_instance_greeter(name)
self.class.send(:private_class_greeter, name)
end
end
Animal.public_class_greeter('John')
# John greets private class method
Animal.new.public_instance_greeter("John")
# John greets private class method
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.