Ruby的。()运算符是如何工作的?

时间:2013-10-01 05:22:56

标签: ruby methods syntax service-object

我最近遇到some code使用的格式为object.(arg1, arg2)的方法调用,但没有看到它的工作原理。请参阅此示例代码:

class TestServiceObject
  def call
    'method'
  end
end

TestServiceObject.new.()
# => 'method'

这种速记的术语是什么?

3 个答案:

答案 0 :(得分:37)

点括号表示法是将参数传递给Ruby对象上的隐式call方法的简便方法:

foo = lambda {|bar| puts bar}

foo.call('baz')
#=> baz
foo.('baz')

foo.call('baz') === foo.('baz')
#=> true

另请注意,以下表示法也是call方法的有效(和等效)调用:

foo['baz']
#=> baz
foo::('baz')
#=> baz

在您的示例中,您显式覆盖call类上的TestServiceObject方法,以便在调用时返回字符串'method'。因此,您可以显式覆盖call方法以接受参数:

class TestServiceObject
  def call(foo=nil)
    foo || 'method'
  end
end

TestServiceObject.new.()
#=> method
TestServicesObject.new.('bar')
#=> bar

<强>更新

正如评论者@LoganSerman正确指出的那样,简写操作符似乎可以处理响应call的任何内容,这部分通过以下示例进行验证:

m = 12.method("+")

m.call(3)
#=> 15
m.(3)
#=> 15

更新2

评论者@Stefan也指出the documentation on Proc#call

  

prc。()使用给定的参数调用prc.call()。隐藏“呼叫”是一种语法糖。

答案 1 :(得分:4)

obj.(args)只是通过解析器提供的功能。从技术上讲,它不是别名,但它与在定义obj.call(args)方法的对象上调用call具有相同的效果。

答案 2 :(得分:4)

foo.(bar, baz)

被解释为

foo.call(bar, baz)

就像

一样
foo + bar

被解释为

foo.+(bar)

foo[bar, baz] = quux

被解释为

foo.[]=(bar, baz, quux)

目的是使类似调用函数的对象看起来类似于调用方法:

foo.(bar, baz) # function
foo(bar, baz)  # method

尽管在这个问题的其他答案中声称,它与“隐式call方法无关”(Ruby甚至没有隐式方法,只有Scala这样做)或者索引运算符。

索引运算符被转换为对[]的调用的不同方法调用(call)和而不是

o = Object.new

def o.call(*args); "`call` called with #{args.join(', ')}" end

o.(42)
# => "`call` called with 42"

o[42]
# NoMethodError: undefined method `[]' for #<Object:0xdeadbeefc0ffee>

def o.[](*args);   "`[]` called with #{args.join(', ')}"   end

o[42]
# => "`[]` called with 42"