gpt4 book ai didi

Ruby 元类 : why three when defined singleton methods?

转载 作者:数据小太阳 更新时间:2023-10-29 07:13:38 25 4
gpt4 key购买 nike

让我们计算 MRI 范围内的类别:

def count_classes
ObjectSpace.count_objects[:T_CLASS]
end
k = count_classes

用类方法定义类:

class A
def self.foo
nil
end
end

然后运行:

puts count_classes - k
#=> 3

请解释一下,为什么是三个?

最佳答案

查看 MRI 代码,每次你创建一个 Class 时,在 Ruby 中它是 Class 类型的对象,ruby 会自动为这个新类创建“元类”类,这是另一个单例类型的 Class 对象。

C 函数调用 (class.c) 是:

rb_define_class
rb_define_class_id
rb_class_new(super);
rb_make_metaclass(klass, RBASIC(super)->klass);

因此,每次您定义一个新类时,Ruby 都会使用元信息定义另一个类。

当你定义一个类方法时,我的意思是,def self.method,在内部,ruby 调用 rb_define_singleton_method。您可以按照以下步骤检查它:

创建一个ruby文件test.rb:

class A
def self.foo
end
end

然后运行以下命令:

ruby --dump insns test.rb

您将得到以下输出:

== disasm: <RubyVM::InstructionSequence:<main>@kcount.rb>===============
0000 trace 1 ( 70)
0002 putspecialobject 3
0004 putnil
0005 defineclass :A, <class:A>, 0
0009 leave
== disasm: <RubyVM::InstructionSequence:<class:A>@kcount.rb>============
0000 trace 2 ( 70)
0002 trace 1 ( 71)
0004 putspecialobject 1
0006 putself
0007 putobject :foo
0009 putiseq foo
0011 opt_send_simple <callinfo!mid:core#define_singleton_method, argc:3, ARGS_SKIP>
0013 trace 4 ( 73)
0015 leave ( 71)
== disasm: <RubyVM::InstructionSequence:foo@kcount.rb>==================
0000 trace 8 ( 71)
0002 putnil
0003 trace 16 ( 72)
0005 leave

define_singleton_method 映射到 rb_obj_define_method C 函数 (object.c),它执行以下调用:

 rb_obj_define_method
rb_singleton_class(obj)
rb_mod_define_method

函数 rb_singleton_class 公开了定义类时创建的元类,但它也为这个元类创建了一个新的元类。

根据这个函数的 Ruby 文档:“如果一个 obj 是一个类,返回的单例类也有自己的单例类,以保持元类继承结构的一致性”。

这就是定义类方法时,类的个数加1的原因。

如果您通过以下方式更改代码,也会产生同样的效果:

class A
end
A.singleton_class

singleton_class 映射到 rb_obj_singleton_class C 函数,它调用 rb_singleton_class

即使创建类方法并调用singleton_class方法,创建类的数量也不会改变,因为处理元信息所需的所有类都已经创建。示例:

class A
def self.foo
nil
end
end

A.singleton_class

上面的代码会一直返回 3。

关于Ruby 元类 : why three when defined singleton methods?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19864275/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com