Почему метаклассы являются экземплярами метакласса, а не класса? - PullRequest
8 голосов
/ 11 декабря 2010

Мне бы хотелось узнать причину, по которой используются два разных класса, а не просто использовать класс для обоих.

Ответы [ 3 ]

5 голосов
/ 11 декабря 2010

Короткий ответ: «Ваше предположение, что классы являются экземплярами общесистемного класса, неверно, каждый класс на самом деле является экземпляром специфичного для класса метакласса», а также «он не будет работать по-другому».

Небольшое изменение в ответе: «имена действительно сбивают с толку, иногда проще просто запомнить их роли и не пытаться слишком много думать о том, как они работают».

Короткий волосатый ответ:

Метакласс является экземпляром, как и все другие обычные классы Smalltalk, и для него требуется собственный выделенный класс. Каждый экземпляр обычного объекта Smalltalk имеет класс, наследование которого следует иерархии классов. Каждый класс сам является экземпляром специфичного для класса метакласса с наследованием в соответствии с иерархией метакласса. Каждый метакласс сам по себе является экземпляром класса Metaclass, который замыкается виртуальной машиной в изящной маленькой хитрости, так как никто не нашел применения, чтобы дать классу Metaclass родительский класс, и все те, кто пытался, обычно находили, что их здравомыслие начало разрушаться в процессе.

Длиннее, все еще волосатый ответ:

Smalltalk позволяет каждому классу содержать сообщения, специфичные для класса. Это примерно эквивалентно статическим методам в Java, но с некоторыми существенными отличиями. Одно из этих отличий состоит в том, что классы Smalltalk на самом деле являются объектами, созданными на основе экземпляра, - это живые объекты в системе, обладающие возможностью наследовать от других объектов и содержать переменные экземпляра.

Это свойство приводит к потенциальному множеству иерархий наследования в системе. Каждый из обычных объектов является экземплярами ровно одного класса, с сообщениями, посылаемыми объектам, которые ищут класс объектов, а затем следуют по цепочке наследования иерархии классов. Сообщения, отправляемые обычным объектам, разрешаются в иерархии классов.

Кроме того, каждый объект класса является экземпляром одного специфического для класса метакласса. Сообщения, отправленные объекту класса, разрешаются путем поиска в метаклассе, специфичном для класса, а затем в иерархии метакласса вверх.

Еще один слой, каждый из объектов метакласса, является экземпляром уникального общесистемного класса метакласса. Сообщения, отправляемые объекту метакласса, просматриваются в общесистемном уникальном метаклассе, который не может наследоваться от кого-либо и который запрограммирован как короткое замыкание в ВМ.

Технически, система имеет две иерархии наследования и третью, имитирующую короткое замыкание. Нет никакой теоретической причины останавливаться на двух, хотя есть много практических. Это позволяет каждому объекту иметь свои собственные, уникальные объекты, сообщения, каждый класс имеет свои собственные, уникальные классы, сообщения и заставляет все метаклассы отвечать только на один набор сообщений, определенный в метаклассе.

Аккуратно, да?

3 голосов
/ 11 декабря 2010

Вам явно необходимы два ClassDescription для класса: одно для методов экземпляра и одно для методов класса.

Теперь вы все равно можете попытаться использовать Class для обоих объектов.Я думаю, что одной из причин наличия метакласса является то, что вам нужно различать их.Если вы посмотрите на методы theMetaClass и theNonMetaClass, вы увидите, что они отражают друг друга: вы переходите от метакласса к классу через член этого класса, а от класса к метаклассу - через обычный указатель класса (которым обладает любой объект).Если они оба принадлежали к классу экземпляра, они не могли знать, какую сторону они реализуют - если только не было места для флага, что хуже, чем создание подклассов.

1 голос
/ 11 декабря 2010

Это одна из тех вещей, которые я прекрасно понимаю ... пока я не объясню это ;-) После большой перегонки ...

Дано:

  • поведение объекта определяется его классом
  • классы тоже объекты
  • обычные объекты / классы имеют поведение, которое имеет смысл только для регулярных объектов / классов

Следовательно, классы и экземпляры должны иметь разные характеристики поведения (т.е. классы).

С другой стороны, то, что мы называем "стороной экземпляра", представляет сторону экземпляра класса . То, что мы называем «стороной класса», представляет сторону экземпляра метакласса .

Например, Class определяет #addClassVarNamed: и #addInstVarNamed:, потому что оба имеют смысл на стороне экземпляра, где Metaclass определяет только #addInstVarNamed:, потому что нет переменных класса на стороне класса.

Чтобы глубже погрузиться в мелочи, см. «Пример Pharo By» или «Основы техники программирования Smalltalk»

...