def myobject.mymeth和class<<之间的区别为MyObject; def mymeth

时间:2012-04-27 03:08:05

标签: ruby singleton singleton-methods

我目前在Ruby中练习/学习单例方法和单例类,我遇到了疑问。给出:

myobject = Object.new

这样做有什么区别:

def myobject.mymethod
end

并且这样做:

class << myobject
 def mymethod
 end
end

如果有,我们何时会使用其中一个?有什么影响?

1 个答案:

答案 0 :(得分:2)

使用 ruby​​ --dump ins 来研究结果,如下所示:

1

# test.rb
myobject = Object.new

def myobject.mymethod
end

执行 ruby​​ --dump ins test.rb

输出是:

D:\>ruby --dump ins test.rb
== disasm: <RubyVM::InstructionSequence:<main>@test.rb>=================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] myobject
0000 trace            1                                               (   1)
0002 getinlinecache   9, <ic:0>
0005 getconstant      :Object
0007 setinlinecache   <ic:0>
0009 send             :new, 0, nil, 0, <ic:1>
0015 setdynamic       myobject, 0
0018 trace            1                                               (   3)
0020 putspecialobject 1
0022 getdynamic       myobject, 0
0025 putobject        :mymethod
0027 putiseq          mymethod
0029 send             :"core#define_singleton_method", 3, nil, 0, <ic:2>
0035 leave
== disasm: <RubyVM::InstructionSequence:mymethod@test.rb>===============
0000 trace            8                                               (   3)
0002 putnil
0003 trace            16                                              (   4)
0005 leave

2

# test.rb
myobject = Object.new

class << myobject
 def mymethod
 end
end

执行 ruby​​ --dump ins test.rb

输出是:

D:\>ruby --dump ins test.rb
== disasm: <RubyVM::InstructionSequence:<main>@test.rb>=================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] myobject
0000 trace            1                                               (   1)
0002 getinlinecache   9, <ic:0>
0005 getconstant      :Object
0007 setinlinecache   <ic:0>
0009 send             :new, 0, nil, 0, <ic:1>
0015 setdynamic       myobject, 0
0018 trace            1                                               (   3)
0020 getdynamic       myobject, 0
0023 putnil
0024 defineclass      :singletonclass, singletonclass, 1
0028 leave
== disasm: <RubyVM::InstructionSequence:singletonclass@test.rb>=========
0000 trace            2                                               (   3)
0002 trace            1                                               (   4)
0004 putspecialobject 1
0006 putspecialobject 2
0008 putobject        :mymethod
0010 putiseq          mymethod
0012 send             :"core#define_method", 3, nil, 0, <ic:0>
0018 trace            4                                               (   6)
0020 leave                                                            (   4)
== disasm: <RubyVM::InstructionSequence:mymethod@test.rb>===============
0000 trace            8                                               (   4)
0002 putnil
0003 trace            16                                              (   5)
0005 leave

所以 def myobject.method 的方式是先将core#define_singleton_method消息发送到myobject, 然后,核心#define_singleton_method消息的实现获取myobject的单例类,并将方法定义添加到 单身人士班。

class&lt;&lt; myobject 的方式是首先将单个类消息发送到myobject,然后将core#define_method消息发送到myobject的单个类。

在实践中,

如果要为obj定义一些单例方法,请使用 class&lt;&lt; OBJ

如果您只为obj定义单例方法,请使用 def obj.method