Введение

Метакласс описывает общее поведение для классов, подобно тому, как класс описывает поведение для объектов.

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

В рамках цели C

Метаклассы в Objective-C почти идентичны метаклассам в Smalltalk 80 — что неудивительно, учитывая, что Objective-C многое позаимствовала у Smalltalk. Как и в Smalltalk, в Objective-C переменные экземпляра и методы определяются классом объекта. Класс является объектом, следовательно, он является экземпляром метакласса. Как и в Smalltalk, в Objective-C методы класса — это просто методы, вызываемые у объекта класса, поэтому методы класса класса должны быть определены как методы экземпляра в его метаклассе. Поскольку разные классы могут иметь разные наборы методов класса, каждый класс должен иметь свой собственный отдельный метакласс. Классы и метаклассы всегда создаются парами: среда выполнения предоставляет функции `objc_allocateClassPair` и `objc_registerClassPair` для создания и регистрации пар «класс-метакласс» соответственно. Метаклассы не имеют имен; однако на любой объект класса можно ссылаться с помощью обобщенного типа `Class` (аналогично типу `id`, используемому для указателя на любой объект). Поскольку методы класса наследуются по цепочке наследования, как и в Smalltalk, метаклассы должны следовать схеме наследования, параллельной схеме наследования классов (например, если родительским классом класса A является класс B, то родительским классом метакласса A является метакласс B), за исключением корневого класса. В отличие от Smalltalk, метакласс корневого класса наследуется непосредственно от корневого класса (обычно `NSObject` при использовании фреймворка Cocoa). Это гарантирует, что все объекты класса в конечном итоге являются экземплярами корневого класса, что позволяет использовать методы экземпляра корневого класса — обычно полезные вспомогательные методы для объектов — для самих объектов класса. Поскольку объекты метакласса не имеют особого поведения (нельзя добавить методы класса для метакласса, поэтому все объекты метакласса имеют одинаковые методы), они все являются экземплярами одного и того же класса — метакласса корневого класса (в отличие от Smalltalk). Таким образом, метакласс корневого класса является экземпляром самого себя. Это связано с тем, что все метаклассы наследуются от корневого класса; следовательно, они должны наследовать методы класса корневого класса.