Класс .superclass= Module, Module.class= Class?

Как это вычисляется? Он круговой

Обновление: (в irb)

Class.superclass = Module
Module.class = Class

Как можно сказать, что класс модуля - это класс, когда класс является модулем подкласс? Это круглая, курица и яйцо.

Object: тот же вопрос: Object - это корневой объект в объектной модели. Как его класс может быть классом, поскольку объект класса еще не существует?

Ответ 1

Посмотрим на файл class.c исходного кода MRI:

void Init_class_hierarchy(void)
{
    id_attached = rb_intern("__attached__");

    rb_cBasicObject = boot_defclass("BasicObject", 0);
    /* boot_defclass is defined as boot_defclass(const char *name, VALUE super) */
    rb_cObject = boot_defclass("Object", rb_cBasicObject);
    rb_cModule = boot_defclass("Module", rb_cObject);
    rb_cClass =  boot_defclass("Class",  rb_cModule);

    /* Very important line: */
    RBASIC(rb_cClass)->klass
          = RBASIC(rb_cModule)->klass
          = RBASIC(rb_cObject)->klass
          = RBASIC(rb_cBasicObject)->klass
          = rb_cClass;
 }

Эти определения в ruby.h также очень важны:

#define R_CAST(st)   (struct st*)
#define RBASIC(obj)  (R_CAST(RBasic)(obj))
#define ROBJECT(obj) (R_CAST(RObject)(obj))
#define RCLASS(obj)  (R_CAST(RClass)(obj))
#define RMODULE(obj) RCLASS(obj)

Обратите внимание, что Object, Module и Class получены из BasicObject. Действительно,

irb(main):001:0> BasicObject.superclass
=> nil

Эти объекты определяются одновременно, и все они имеют RBASIC(*)->klass = rb_cClass.

Ответ 2

x.superclass и x.class имеют разную семантику. Обратите внимание:

irb(main):003:0> 3.superclass
NoMethodError: undefined method `superclass' for 3:Fixnum
    from (irb):3
    from :0
irb(main):004:0> 3.class
=> Fixnum

3 не имеет superclass, потому что... 3 не является классом или чем-то вроде этого. Но 3.class означает класс, что 3 является экземпляром.

Так что вещь, которая должна соответствовать Class.superclass, не Module.class, а Module сама.

Ответ 3

Круговая зависимость работает, потому что это все встроенные классы. Они являются частью основной среды Ruby и настроены таким образом при запуске и не добавляются так, как вы обычно добавляете класс. Время выполнения имеет право настроить указатели, но он хочет, и дизайнер решил сделать это таким образом.