ruby 中的“&method(:method_ name)”是什么意思?
What does `&method(:method_ name)` mean in ruby?
我试图创建一个具有私有 class 方法的 class。我希望这个私有 class 方法可以在实例方法中使用。
以下是我的第一次尝试:
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')
工作正常,打印 John greets private class method
.
但是,Animal.new.public_instance_greeter("John")
抛出错误:NoMethodError: private method 'private_class_greeter' called for Animal:Class
。
这是预期的,因为调用 self.class.private_class_greeter
与 Animal.private_class_greeter
相同,这显然会引发错误。
在搜索了如何解决这个问题之后,我想到了以下代码,它可以完成工作:
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
我不太明白这里发生了什么:&method(:private_class_greeter)
。
你能解释一下这是什么意思吗?
如果我要替换:
define_method :public_instance_greeter, &method(:private_class_greeter)
与:
def public_instance_greeter
XYZ
end
那么,XYZ
的内容应该是什么?
Ruby如何解析&method(:private_class_greeter)
?
表达式&method(:private_class_greeter)
是
- 方法调用的值
method(:private_class_greeter)
- 以
&
运算符为前缀。
method
方法有什么作用?
method
方法在当前上下文中查找指定的方法名称和 returns 表示它的 Method
对象。 irb
中的示例:
def foo
"bar"
end
my_method = method(:foo)
#=> #<Method: Object#foo>
一旦你掌握了这个方法,你就可以用它做各种事情:
my_method.call
#=> "bar"
my_method.source_location # gives you the file and line the method was defined on
#=> ["(irb)", 5]
# etc.
&
运算符有什么用?
&
运算符用于 将 Proc
作为块传递给方法 要传递给它的块。它还对您传入的值隐式调用 to_proc
方法,以便将不是 Proc
的值转换为 Proc
.
Method
class 实现了 to_proc
— 它 returns 方法的内容作为 Proc
。因此,您可以在 Method
实例前面加上 &
并将其作为块传递给另一个方法:
def call_block
yield
end
call_block &my_method # same as `call_block &my_method.to_proc`
#=> "bar"
define_method
方法恰好占用了一个块,其中包含正在定义的新方法的内容。在您的示例中,&method(:private_class_greeter)
将现有的 private_class_greeter
方法作为一个块传递。
这是&:symbol
的工作方式吗?
是的。 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) }
如何复制&method(:private_class_greeter)
?
您可以传入调用目标方法的块:
define_method :public_instance_greeter do |name|
self.class.send(:private_class_greeter, name)
end
当然,那么你就不需要再使用define_method
了,结果就是Eric在中提到的相同解决方案:
def public_instance_greeter(name)
self.class.send(:private_class_greeter, name)
end
首先,注意你的缩进。 private
应该是右边的 2 个空格:它给人的印象是 public_instance_greeter
否则是私有的。
如果你不关心封装,你可以简单地使用 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
我试图创建一个具有私有 class 方法的 class。我希望这个私有 class 方法可以在实例方法中使用。
以下是我的第一次尝试:
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')
工作正常,打印 John greets private class method
.
但是,Animal.new.public_instance_greeter("John")
抛出错误:NoMethodError: private method 'private_class_greeter' called for Animal:Class
。
这是预期的,因为调用 self.class.private_class_greeter
与 Animal.private_class_greeter
相同,这显然会引发错误。
在搜索了如何解决这个问题之后,我想到了以下代码,它可以完成工作:
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
我不太明白这里发生了什么:&method(:private_class_greeter)
。
你能解释一下这是什么意思吗?
如果我要替换:
define_method :public_instance_greeter, &method(:private_class_greeter)
与:
def public_instance_greeter
XYZ
end
那么,XYZ
的内容应该是什么?
Ruby如何解析&method(:private_class_greeter)
?
表达式&method(:private_class_greeter)
是
- 方法调用的值
method(:private_class_greeter)
- 以
&
运算符为前缀。
method
方法有什么作用?
method
方法在当前上下文中查找指定的方法名称和 returns 表示它的 Method
对象。 irb
中的示例:
def foo
"bar"
end
my_method = method(:foo)
#=> #<Method: Object#foo>
一旦你掌握了这个方法,你就可以用它做各种事情:
my_method.call
#=> "bar"
my_method.source_location # gives you the file and line the method was defined on
#=> ["(irb)", 5]
# etc.
&
运算符有什么用?
&
运算符用于 将 Proc
作为块传递给方法 要传递给它的块。它还对您传入的值隐式调用 to_proc
方法,以便将不是 Proc
的值转换为 Proc
.
Method
class 实现了 to_proc
— 它 returns 方法的内容作为 Proc
。因此,您可以在 Method
实例前面加上 &
并将其作为块传递给另一个方法:
def call_block
yield
end
call_block &my_method # same as `call_block &my_method.to_proc`
#=> "bar"
define_method
方法恰好占用了一个块,其中包含正在定义的新方法的内容。在您的示例中,&method(:private_class_greeter)
将现有的 private_class_greeter
方法作为一个块传递。
这是&:symbol
的工作方式吗?
是的。 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) }
如何复制&method(:private_class_greeter)
?
您可以传入调用目标方法的块:
define_method :public_instance_greeter do |name|
self.class.send(:private_class_greeter, name)
end
当然,那么你就不需要再使用define_method
了,结果就是Eric在
def public_instance_greeter(name)
self.class.send(:private_class_greeter, name)
end
首先,注意你的缩进。 private
应该是右边的 2 个空格:它给人的印象是 public_instance_greeter
否则是私有的。
如果你不关心封装,你可以简单地使用 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