Ruby中的方法:对象与否?

受到这个讨论的启发,在googlesearch一下后,我无法find关于Ruby中的方法的一个非常简单的问题的答案:方法对象还是不是?

在这里和那里有不同的意见,我真的很想听到,比方说,深入的解释。

我知道Object#method方法,它采用一个方法名并返回一个Method实例,但另一方面,你可以用块做类似的事情,使它们成为Proc实例,块不是对象,那么什么使方法有所不同呢?

方法是Ruby语法的基本部分,但它们不是Ruby程序可以运行的值。 也就是说, Ruby的方法不是string,数字和数组的方式。 然而,获取表示给定方法的Method对象是可能的,我们可以通过Method对象间接调用方法。

从Ruby编程语言 :
替代文字http://ecx.images-amazon.comhttp://img.dovov.comI/517LDwIEYwL._SL75_.jpg

你真的不知道。

访问方法的唯一方法是将#method消息发送给某个对象,然后返回一个Method对象。 但是,方法本身对象的方法吗? 或者它是一个方法的包装? 或者它是原始方法的转换版本?

你不知道:如果你想看一个方法,你必须调用#method ,在这一点上,你肯定得到一个对象。 你之前#method你不能看,所以你不能告诉。

几个数据点:在Ruby中,一切都返回一个值。 def返回什么? 它总是返回nil ,不是一个Method对象。 和define_method ? 它返回一个Proc ,但不是一个Method (也不是一个UnboundMethod )。 [注:在Rubinius中, def返回方法的编译字节码,但仍不是Method对象。]

如果你看Ruby语言规范6.1节(第5页和第6页第29-34行和第1-5行)的第4段和第5段,可以清楚地看到在方法和对象之间有区别。 如果你看看内build类的规范,你会发现既没有Method也没有UnboundMethod ,也没有Object#method 。 IOW:您可以构build完全符合标准的Ruby解释器,其中方法不是对象。

现在,阻止OTOH绝对不是对象。 有很多方法从块构造 Proc对象,然后它们具有与原始块( lambdaprocProc.new& sigil)相同的行为,但是块本身不是对象。

想想这样:你可以传递一个string到File.new来构造一个文件对象,但是这不会使string成为一个文件。 您可以将一个块传递给Proc.new来构造一个proc对象,但是这不会使块成为一个proc对象。

在Ruby中,方法和块本身不是本地的或头等的对象。 但是,它们可以非常容易地包裹在物体中,因此它们通常没有区别。

但是试试,并且记住的结果,

 a = Object.method(:new).object_id b = Object.method(:new).object_id a == b => false 

在Haskell中,所有的值(包括数字以及lambdas和函数)都是一stream的值。 在语言的每一个方面,它们都被等同对待。 Ruby中不是这样,但可以近似。

对象和方法不一样,即使方法的返回值是一个对象而不是零。 除非在方法,lambda或proc范围内,并且方法本身位于堆栈上,并且在解释之后分配地址,而在堆上分配静态和类对象,否则对象将位于堆上。 Ruby仍然使用C来解释它并将其传递给VALUE结构体。

由于括号在ruby中是可选的,所以方法对象通常是“隐藏的”,您需要通过method方法显式地获取方法对象。 但是,如果您努力捕获一个方法对象,就会非常清楚它的行为像一个对象。 由于Ruby> = 2.1,所以比以往更容易利用。

例如,你可以让你的方法的行为更像Javascript中的方法(没有parens是方法对象,parens被用来调用方法),像这样:

 foo = method def foo def a(num) 3 * num.to_i end n = yield if block_given? a(n || 3) rescue "oops!" end def foo.bar(num) a(num) end foo.class #=> Method foo() #=> 9 foo.call #=> 9 foo.call{2} #=> 6 foo(){2} #=> 6 foo.call{ raise "blam!" } #=> "oops!" foo.bar(5) #=> 15 

将这些示例写入testing版本, 请参阅此要点 。

JRL的回答引用了Matz的书,说方法不是像string等对象,但是方法对象是真实的,除了parens / no-parens之外,它们的行为与其他任何ruby对象非常相似。 这是一种鸭子式的语言 ,所以我会说在我的书中有资格的方法作为对象。