Подтвердить что ты не робот

Недостаток метакласса Ruby

Я понимаю, что все классы в ruby ​​являются экземплярами класса metaclass. И эти "обычные" объекты являются экземплярами этих классов (экземпляры класса метакласса).

Но я продолжаю задаваться вопросом, я имею в виду, что классы являются корнями из объектов, классы сами являются экземплярами класса (называются метаклассом, потому что его экземпляры являются классами). В некоторых блогах я видел некоторое переопределение метода new класса Class.

Итак, класс ведет себя как класс, но его экземплярами являются классы. Итак, кажется, что у нас есть круг, он выглядит как класс Class - это сам экземпляр.

Мне явно не хватает места. Каково происхождение класса Class?

Вот пример, который меня смущает:

class Class
  def new
    #something
  end
end

Но ключевое слово class подразумевает экземпляр класса Class. Итак, как это работает?

4b9b3361

Ответ 1

как это работает

Просто: это не так. Во всяком случае, не в Ruby.

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

В Ruby некоторые из этих волшебных вещей:

  • Object не имеет суперкласса, но вы не можете определить класс без суперкласса, неявный прямой суперкласс всегда Object. [Примечание: могут быть реализационные суперклассы Object, но в конечном итоге будет один, у которого нет суперкласса.]
  • Object - это экземпляр Class, который является подклассом Object (что означает, что косвенно Object является экземпляром самого Object)
  • Class является подклассом Module, который является экземпляром Class
  • Class - это экземпляр Class

Ни одна из этих вещей не может быть объяснена в Ruby.

BasicObject, Object, Module и Class все должны существовать spring в то же время, потому что они имеют круговые зависимости.

Просто потому, что это отношение не может быть выражено в коде Ruby, не означает, что спецификация языка Ruby не может сказать, что это должно быть так. Именно разработчику предстоит выяснить способ сделать это. В конце концов, реализация Ruby имеет уровень доступа к объектам, которые вы, как программист, не имеете.

Например, реализация Ruby может сначала создать BasicObject, установив как его указатель superclass, так и указатель Class на null.

Затем он создает Object, устанавливая указатель superclass на BasicObject и его указатель Class на null.

Затем он создает Module, устанавливая указатель superclass на Object и его указатель Class на null.

Наконец, он создает Class, устанавливая указатель superclass на Module и его указатель Class на null.

Теперь мы можем переписать BasicObject 's, Object' s, ModuleClass Class указатель на Class, и мы закончили.

Это легко сделать извне системы, оно просто выглядит странно изнутри.

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

В вашем примере class Class не создает новый класс с именем Class, он снова открывает существующий класс Class, который был предоставлен нам средой выполнения.

Итак, вполне возможно объяснить поведение по умолчанию Class#new в обычном Ruby:

class Class
  def new(*args, &block)
    obj = allocate # another magic thing that cannot be explained in Ruby
    obj.initialize(*args, &block)
    return obj
  end
end

[Примечание: на самом деле initialize является закрытым, поэтому вам нужно использовать obj.send(:initialize, *args, &block), чтобы обойти ограничение доступа.]

BTW: Class#allocate - еще одна из этих волшебных вещей. Он выделяет новый пустой объект в пространстве объектов Ruby, что не может быть сделано в Ruby. Таким образом, Class#allocate - это то, что также должно быть обеспечено системой исполнения.

Ответ 2

Да, класс - это сам экземпляр. Это подкласс модуля, который также является экземпляром класса, а Module является подклассом Object, который также является экземпляром класса. Это действительно круто, но это часть основного языка, а не что-то в библиотеке. Сама среда Ruby сама не имеет того же предела, что и вы, или я, когда мы пишем код Ruby.

Я никогда не слышал, чтобы слово "метакласс" использовалось для разговоров о классе. Он вообще не используется в Ruby, но когда он есть, он обычно является синонимом того, что официально называется "одноэлементным классом объекта", что является еще более запутанной темой, чем треугольник Object-Module-Class.

Ответ 3

Существует мета-круглость, заданная ссылкой "поворот". Это встроенная ссылка суперкласса от корневого eigenclass к классу Class. Это можно выразить через

BasicObject.singleton_class.superclass == Class

Ключ к пониманию карты .class показывает эту карту как производную от ссылок eigenclass и superclass: для объекта x, x.class является первым классом в цепочке суперкласса x eigenclass. Это можно выразить через

x.class == x.eigenclass.superclass(n)

где eigenclass является "концептуальным псевдонимом" singleton_class (устойчив к проблемам с немедленными значениями), y.superclass(i) означает i -th суперкласс y и n наименьший, так что x.eigenclass.superclass(n) является классом. Эквивалентно, eigenclasses в цепочке суперкласса x.eigenclass пропущены (см. rb_class_real, который также показывает, что в MRI даже ссылки superclass реализованы косвенно – они возникают, пропуская " iclasses" ). Это приводит к тому, что Class для каждого класса (а также для каждого eigenclass) постоянно является классом Class.

Изображение предоставлено этой диаграммой.

Метаклассная путаница имеет 2 основных источника:

  • Smalltalk. Объектная модель Smalltalk-80 содержит концептуальные несоответствия, которые исправляются объектной моделью Ruby. Кроме того, литература Smalltalk использует диалектику в терминологии, которая, к сожалению, недостаточно исправлена ​​в литературе Ruby.

  • Определение метакласса . В настоящее время в определении указано, что метаклассы являются классами классов. Однако для так называемых " неявных метаклассов" (в случае Ruby и Smalltalk-80) гораздо более подходящее определение было бы для метаобъектов классов.