Метакласс - Metaclass

В объектно-ориентированного программирования, а метакласс это учебный класс чьи экземпляры являются классами. Так же, как обычный класс определяет поведение определенных объектов, метакласс определяет поведение определенных классов и их экземпляров. Не все объектно-ориентированные языки программирования поддерживать метаклассы. Среди тех, которые это делают, степень, в которой метаклассы могут переопределить любой заданный аспект поведения класса, варьируется. Метаклассы могут быть реализованы, если классы первоклассный гражданин, и в этом случае метакласс - это просто объект, который создает классы. У каждого языка своя протокол метаобъектов, набор правил, регулирующих взаимодействие объектов, классов и метаклассов.[1]

Пример Python

В Python, встроенный класс тип это метакласс.[2][3][4] Рассмотрим этот простой класс Python:

учебный класс Машина:    def __в этом__(себя, делать: ул., модель: ул., год: int, цвет: ул.) -> Никто:        себя.делать = делать        себя.модель = модель        себя.год = год        себя.цвет = цвет    @свойство    def описание(себя):        "" "Вернуть описание этой машины." ""        возвращаться ж"{self.color}{self.year}{self.make}{self.model}"

Во время выполнения Машина сам по себе является примером тип. Исходный код Машина класс, показанный выше, не включает такие детали, как размер в байтах Машина объекты, их двоичное расположение в памяти, как они распределяются, что __в этом__ метод автоматически вызывается каждый раз, когда Машина создается и так далее. Эти детали вступают в игру не только при появлении нового Машина объект создается, но также каждый раз, когда любой атрибут Машина доступен. В языках без метаклассов эти детали определяются спецификацией языка и не могут быть изменены. В Python метакласс - тип - контролирует эти детали Машинаповедение. Их можно переопределить, используя другой метакласс вместо тип.

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

учебный класс AttributeInitType(тип):    def __вызов__(себя, *аргументы, **kwargs):        "" "Создать новый экземпляр." ""        # Сначала создайте объект обычным способом по умолчанию.        объект = тип.__вызов__(себя, *аргументы)        # Дополнительно установите атрибуты на новый объект.        за имя, ценить в kwargs.Предметы():            setattr(объект, имя, ценить)        # Вернуть новый объект.        возвращаться объект

Этот метакласс отменяет только создание объекта. Все остальные аспекты поведения классов и объектов по-прежнему обрабатываются тип.

Теперь класс Машина можно переписать для использования этого метакласса. В Python 3 это делается с помощью «аргумента ключевого слова». метакласс к определению класса:

учебный класс Машина(объект, метакласс=AttributeInitType):    @свойство    def описание(себя):        "" "Вернуть описание этой машины." ""        возвращаться " ".присоединиться(ул.(ценить) за ценить в себя.__dict__.значения())

Результирующий объект Машина могут быть созданы как обычно, но могут содержать любое количество аргументов ключевого слова:

Новый автомобиль = Машина(делать='Тойота', модель='Prius', год=2005, цвет='Зеленый', двигатель='Гибридный')

В Smalltalk-80

Иерархия метакласса Smalltalk-80 как диаграмма UML
Схема наследования и отношений экземпляров между классами и метаклассами в Smalltalk

В Болтовня, все объект. Кроме того, Smalltalk - это на основе класса system, что означает, что у каждого объекта есть класс, который определяет структуру этого объекта (то есть переменные экземпляра, которые имеет объект) и сообщения, которые понимает объект. Вместе это означает, что класс в Smalltalk является объектом и, следовательно, класс должен быть экземпляром класса (называемого метаклассом).

Например, автомобильный объект c является экземпляром класса Машина. В свою очередь, класс Машина снова является объектом и как таковой экземпляр метакласса Машина называется Класс автомобиля. Обратите внимание на пробел в имени метакласса. Имя метакласса - это выражение Smalltalk, которое при вычислении приводит к объекту метакласса. Таким образом оценивая Класс автомобиля приводит к объекту метакласса для Машина чье имя Класс автомобиля (это можно подтвердить, оценив Название класса автомобиля который возвращает имя метакласса Машина.)

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

Когда сообщение отправлено на Целое число поиск метода начинается в Целочисленный класс и переходит вверх по цепочке суперкласса к Класс объекта. Обратите внимание, что до сих пор цепочка наследования метакласса в точности повторяет цепочку наследования классов. Но цепочка метаклассов расширяется дальше, потому что Класс объекта является подклассом Учебный класс. Все метаклассы являются подклассами класса.

В ранних версиях Smalltalks был только один метакласс, называемый Учебный класс. Это означало, что методы все классы были одинаковы, в частности метод создания новых объектов, т.е. новый. Чтобы позволить классам иметь свои собственные методы и собственные переменные экземпляра (называемые переменными экземпляра класса, и их не следует путать с переменные класса ), Smalltalk-80 введен для каждого класса C собственный метакласс C класс. Это означает, что каждый метакласс фактически является одиночка учебный класс.

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

В Smalltalk-80 каждый класс (кроме Объект) имеет суперкласс. В абстрактный суперкласс всех метаклассов Учебный класс, который описывает общий характер классов.

Иерархия суперклассов для метаклассов аналогична иерархии классов, за исключением класса. Объект. ВСЕ метаклассы являются подклассами Учебный класс, следовательно:

  • Суперкласс класса объекта == Class.

Нравиться сиамские близнецы, классы и метаклассы рождаются вместе. Метакласс имеет переменную экземпляра этот класс, что указывает на его объединенный класс. Обратите внимание, что обычный Smalltalk браузер классов не показывает метаклассы как отдельные классы. Вместо этого браузер классов позволяет редактировать класс вместе с его метаклассом одновременно.

Имена классов в иерархии метаклассов легко спутать с одноименными концепциями. Например:

  • Объект это базовый класс, который предоставляет общие методы для всех объектов; "объект" - это целое число, или виджет, или Машина, так далее.
  • Учебный класс является базой метаклассов, которая предоставляет общие методы для всех классов (хотя сам метакласс не является); "класс" это что-то вроде Целое число, или же Виджет, или же Машина, так далее.
  • Метакласс предоставляет общие методы для всех метаклассов.

Четыре класса предоставляют возможности для описания новых классов. Их иерархия наследования (от Object), и основные возможности, которые они предоставляют:

Объект - поведение по умолчанию, общее для всех объектов, например доступ к классу
Поведение - минимум государственный за составление методы и создание / запуск объектов
Описание класса (абстрактный класс ) - название класса / переменной, комментарии
Класс - аналогичные, более широкие возможности суперклассов
Метакласс - инициализация переменных класса, сообщения о создании экземпляра

В Ruby

Ruby очищает концепцию метаклассов Smalltalk-80, вводя собственные классы, удаляя Метакласс class, и (отмена) переопределения class-of map. Изменение можно схематизировать следующим образом:[5]

Smalltalk-80
Классы
Скрытый
метаклассы
  
Терминал
объекты
Рубин
Классы
Собственные классы
классы
Собственные классы
из
собственные классы
Терминал
объекты
Собственные классы
терминальные объекты

В частности, обратите внимание на соответствие между неявными метаклассами Smalltalk и собственными классами классов Ruby. Модель собственных классов Ruby делает концепцию неявных метаклассов полностью единообразной: каждый объект Икс имеет собственный мета-объект, называемый собственный класс из Икс, что на один мета-уровень выше, чем Икс. Собственные классы «более высокого порядка» обычно существуют чисто концептуально - они не содержат никаких методов и не хранят никаких (других) данных в большинстве программ Ruby.[6]

На следующих диаграммах показано сравнение типовой структуры ядра Smalltalk-80 и Ruby.[7]В обоих языках структура состоит из встроенной части, которая содержит круглые объекты (т.е. объекты, которые появляются в цикле, образованном комбинацией синих или зеленых ссылок), и пользовательской части, которая имеет четыре явных объекта: классы А и Bи терминальные объекты ты и vЗеленые ссылки показывают отношение наследования дочерний → родительский (с неявным направлением вверх), синие ссылки показывают отношение дополнительного элемента → контейнера создания экземпляра (синяя ссылка из Икс указывает на наименее актуальный контейнер Икс это начальная точка для поиска метода, когда метод вызывается на Икс). Серые узлы отображают собственные классы (соответственно неявные метаклассы в случае Smalltalk-80).

Smalltalk-80 Рубин
Неявные метаклассы в Smalltalk-80 - образец структурыСобственные классы в Ruby - образец структуры

На диаграмме справа также представлено изображение ленивая оценка собственных классов в Ruby. В v объект может иметь свой собственный класс, оцененный (выделенный) в результате добавления одноэлементные методы к v.

Согласно методу самоанализа Ruby, названному учебный класс, класс каждого класса (и каждого собственного класса) постоянно является Учебный класс класс (обозначается c на схеме).Учебный класс, и Struct являются единственными классами, у которых есть классы как экземпляры.[8][оспаривается ] Подклассы Учебный класс запрещено. Следуя стандартному определению метаклассов, мы можем заключить, что Учебный класс и Struct являются единственными метаклассами в Ruby. Похоже, что это противоречит соответствию между Ruby и Smalltalk, поскольку в Smalltalk-80 каждый класс имеет свой собственный метакласс. Несоответствие основано на несогласии между ними. учебный класс метод интроспекции в Ruby и Smalltalk. Пока карта х ↦ х.учебный класс на терминальных объектах совпадает, отличается ограничением на классы. Как уже было сказано выше, для класса Икс, выражение Ruby Икс.учебный класс постоянно оценивает Учебный класс. В Smalltalk-80, если Икс является классом, тогда выражение Икс учебный класс соответствует рубиновым Икс.singleton_class- который оценивает собственный класс Икс.

В Objective-C

Схема наследования и отношений экземпляров между классами и метаклассами в Objective-C. Обратите внимание, что Objective-C имеет несколько корневых классов; каждый корневой класс будет иметь отдельную иерархию. Эта диаграмма показывает только иерархию для примера корневого класса NSObject. Каждый другой корневой класс будет иметь аналогичную иерархию.

Метаклассы в Objective-C почти такие же, как и в Smalltalk-80, что неудивительно, поскольку Objective-C многое заимствует из Smalltalk. Как и в Smalltalk, в Objective-C переменные и методы экземпляра определяются классом объекта. Класс - это объект, следовательно, это экземпляр метакласса.

Как и в Smalltalk, в Objective-C методы класса - это просто методы, вызываемые для объекта класса, поэтому методы класса должны быть определены как методы экземпляра в его метаклассе. Поскольку разные классы могут иметь разные наборы методов класса, каждый класс должен иметь свой собственный отдельный метакласс. Классы и метаклассы всегда создаются как пара: среда выполнения имеет функции objc_allocateClassPair () и objc_registerClassPair () для создания и регистрации пар класс-метакласс соответственно.

У метаклассов нет имен; однако указатель на любой объект класса может упоминаться с помощью универсального типа Учебный класс (аналогично типу я бы используется для указателя на любой объект).

Поскольку методы класса наследуются посредством наследования, как и Smalltalk, метаклассы должны следовать схеме наследования, параллельной схеме наследования классов (например, если родительский класс класса A является классом B, то родительский класс метакласса A является метаклассом B), за исключением корневого класса.

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

Поскольку объекты метакласса не ведут себя по-разному (вы не можете добавлять методы класса для метакласса, поэтому все объекты метакласса имеют одинаковые методы), все они являются экземплярами одного и того же класса - метакласса корневого класса (в отличие от Smalltalk). Таким образом, метакласс корневого класса является экземпляром самого себя. Причина этого в том, что все метаклассы наследуются от корневого класса; следовательно, они должны наследовать методы класса корневого класса.[9]

Поддержка языков и инструментов

Ниже приведены некоторые из наиболее известных языки программирования которые поддерживают метаклассы.

Некоторые менее распространенные языки, поддерживающие метаклассы, включают OpenJava, OpenC ++, OpenAda, CorbaScript, ObjVLisp, Объект-Z, МОДЕЛЬ-К, XOTcl, и MELDC. Некоторые из этих языков появились в начале 1990-х годов и представляют академический интерес.[11]

Logtalk, объектно-ориентированное расширение Пролог, также поддерживает метаклассы.

Структура описания ресурсов (RDF) и Единый язык моделирования (UML) оба поддерживают метаклассы.

Смотрите также

Рекомендации

  1. ^ Ира Р. Форман и Скотт Данфорт (1999). Запуск метаклассов в работу. ISBN  0-201-43305-2.
  2. ^ Программирование IBM Metaclass на Python, части 1 В архиве 2008-09-03 на Wayback Machine, 2 и 3
  3. ^ Форум Artima: Метаклассы в Python 3.0 (часть 1 из 2) (часть 2 из 2)
  4. ^ Дэвид Мертц. "Учебник по программированию метаклассов Python". ONLamp. Архивировано из оригинал 30 апреля 2003 г.. Получено 28 июня, 2006.
  5. ^ "Объектная модель Ruby: сравнение с Smalltalk-80".
  6. ^ Паоло Перротта (2010). Метапрограммирование Ruby. Прагматическая книжная полка. ISBN  978-1-934356-47-0.
  7. ^ «Принадлежность к объекту: основная структура объектной технологии».
  8. ^ "Struct". Руби Док. Получено 1 мая 2015.
  9. ^ Какао с любовью: что такое мета-класс в Objective-C?
  10. ^ Херб Саттер. «Метаклассы» (PDF).
  11. ^ «Реализация миксинов на Java с использованием метаклассов» (PDF). Архивировано из оригинал (PDF) на 2007-10-16. Получено 2007-11-27.