如何在Ruby中定义未命名的方法?

时间:2016-06-21 11:07:58

标签: ruby

当我突然对其documentation中未命名方法的实现感到好奇时,我正在读取gem gem。

特别是下面的代码:

CommentCell.(@comment).()

cell(:comment, @song).(:index)

它使用没有方法名称的.(arguments)

我确信答案就在源代码本身的某个地方。但是简要地看Cell::ViewModel并没有立即帮助我,所以我只是想知道在彻底检查源代码之前是否有人知道如何做到这一点,并希望满足我的好奇心。

我可以在我即将制作的应用中看到这种用法。

2 个答案:

答案 0 :(得分:4)

.()看起来像缺少方法名称的方法调用。这是一个用于调用call方法的语法糖。它可以与定义调用方法的任何对象一起使用,并与Proclambda一起使用。

class Test
  def call
    puts "test"
  end
end

t = Test.new
t.()
# => "test"
lambda {puts "test"}.()
Proc.new {puts "test"}.()

但是还有其他可能的解决方案可以对.()做出反应。您可以覆盖method_missing或设置别名。

class Test
  def test
    puts "test"
  end

  alias call test;
end

t = Test.new
t.()
# => "test"

答案 1 :(得分:1)

如果你想弄清楚特定语法片段转换为什么方法,你可以自己试试:

class << foo = BasicObject.new
  def method_missing(meth, *args)
    $>.puts "`foo.#{meth}(#{args.inspect[1...-1]})`"
  end

  BasicObject.instance_methods.each(&method(:undef_method))
end

print '`foo.(1, 2, 3)` gets translated to '
foo.(1, 2, 3)
# `foo.(1, 2, 3)` gets translated to `foo.call(1, 2, 3)`

print '`not foo` gets translated to '
not foo
# `not foo` gets translated to `foo.!()`

print '`+foo` gets translated to '
+foo
# `+foo` gets translated to `foo.+@()`

print '`~foo` gets translated to '
~foo
# `~foo` gets translated to `foo.~()`

print '`foo[1, 2, 3] = 4` gets translated to '
foo[1, 2, 3] = 4
`foo[1, 2, 3] = 4` gets translated to `foo.[]=(1, 2, 3, 4)`

等等......

如您所见,foo.(bar, baz)已转换为foo.call(bar, baz)