Lecture
Metamodel, metamodelling, metaclass and metaobject are connected through levels of abstraction in object-oriented and model-driven approaches: a metamodel describes the language of models, metamodelling is the process of constructing it, a metaclass is an element of the metamodel, and a metaobject is an instance of a metaclass that governs objects and their structure.
These terms belong to the same «meta family»: they describe systems at a level above ordinary models, that is, models about models. Let us work through the connection carefully and systematically.
The general idea (meta levels)
There is a hierarchy of levels (often in the spirit of the Object Management Group / MOF):
Basic concepts
| Concept | Definition | Role in the hierarchy |
|---|---|---|
| Model | An abstract representation of a system (for example, a UML class diagram). | Level M1 |
| Metamodel | A model that describes a modelling language (for example, UML as a metamodel for diagrams). | Level M2 |
| Metamodelling | The process of analysing, constructing and evolving metamodels. | An activity linking M2 and M3 |
| Metaclass | A class in a metamodel that defines the rules for the classes of a model (for example, Class, Association in UML). | An element of M2 |
| Metaobject | An instance of a metaclass that describes structure or governs objects (for example, the object «the Person class» as an instance of the metaclass Class). | Level M1/M2 |

How they are connected
Model ↔ Metamodel
Every model must conform to its metamodel.
Example: a UML class diagram (a model) conforms to the UML metamodel.
Metamodel ↔ Metamodelling
Metamodelling is the process of creating a metamodel, that is, a language for describing models.
In the OMG standards, MOF (Meta-Object Facility) is used as the language for metamodelling.
Metamodel ↔ Metaclass
A metamodel consists of metaclasses.
A metaclass sets the rules: what properties and relationships the elements of a model may have.
Metaclass ↔ Metaobject
A metaclass defines the structure, while a metaobject is its concrete realization.
In object-oriented databases, metaobjects describe the structures of the stored objects and govern the core of the system
This is a model that describes other models
Example:
That is:
Metamodel = the rules + structure for building models
Metamodelling is the process of creating a metamodel
That is:
Example:
Metamodelling = the activity
Metamodel = the result
A metamodel is a model of a model, and metamodelling is the process of creating such metamodels. Thus metamodelling is the analysis, construction and development of the frames, rules, constraints, models and theories applicable and useful for modelling a predefined class of problems. As the name suggests, this concept applies the notions of meta- and modelling in software engineering and systems engineering . Metamodels come in various types and have diverse fields of application.
A metamodel/surrogate model is a model of a model, that is, a simplified model of an actual model of a schema, a system or a software-like entity. A metamodel may be a mathematical relation or an algorithm describing input and output relationships. A model is an abstraction of phenomena in the real world ; a metamodel is yet another abstraction, highlighting properties of the model itself. A model conforms to its metamodel in the same way that a computer program conforms to the grammar of the programming language in which it is written. Various types of metamodels include polynomial equations, neural networks, kriging, and so on. «Metamodelling» is the construction of a collection of «concepts» (things, terms, etc.) within a certain domain. Metamodelling typically involves studying the output and input relationships and then fitting suitable metamodels to represent that behaviour.
Metamodels are often used in the following cases:
In view of the «meta» nature of metamodelling, both the practice and the theory of metamodels are relevant to metascience , metaphilosophy , metatheories , systems engineering and metacognition. This concept can be useful in mathematics and has practical applications in computer science and computer engineering / software engineering .

The DoDAF metamodel. DefinitionIn software development, the use of models is an alternative to the more widespread code-based development methods. A model always conforms to a unique metamodel. One of the most active current directions of model-driven development is the approach called model-driven architecture, proposed by the OMG . This approach is embodied in the Meta Object Facility (MOF) specification. [ Typical metamodelling specifications proposed by the OMG include UML , SysML , SPEM or CWM. ISO has also published the standard metamodel ISO/IEC 24744. All the languages presented below can be defined as MOF metamodels.Metadata modellingMetadata modelling is a type of metamodelling used in software engineering and systems engineering to analyse and construct models applicable and useful for a particular class of problems. (see also: data modelling ).Model transformationsAn important step in the development of models is the systematic use of model transformation languages . The OMG has proposed a standard for this called QVT ( Queries/Views/Transformations). QVT is based on the Meta Object Facility (MOF). Among the many other model transformation languages (MTLs), examples of implementations of this standard are AndroMDA, VIATRA , Tefkat , MT , ManyDesigns Portofino .Relation to ontologiesMetamodels are closely related to ontologies . Both are often used to describe and analyse relationships between concepts:
In the field of software engineering, several types of models (and the corresponding kinds of modelling) can be distinguished:
A library of such metamodels is called a metamodel zoo. There are several types of metamodel zoos. Some of them are represented in ECore. Others are written in MOF 1.4 – XMI 1.2. Metamodels represented in UML - XMI 1.2 can be loaded into Poseidon for UML, a UML CASE tool .
This is a class that describes classes
The relationship between levels:
Example:
in Python:
class MyClass:
pass
type(MyClass) # this is a metaclass
type — a metaclass
Metaclass = a builder of classes
In object-oriented programming, a metaclass is a class whose syntactic definitions are used to syntactically define classes themselves. Unlike ordinary classes, which define the behaviour of objects, metaclasses define the behaviour of classes and of their instances. Not all object-oriented programming languages support the concept of metaclasses. For those that do, the degree of control metaclasses have over class behaviour varies. Metaclasses are often implemented by treating classes as first-class objects , which makes a metaclass an object that creates and manages those classes. Every programming language adheres to its own metaobject protocol , which is the set of rules governing the interaction between objects, classes and metaclasses. Metaclasses are used to automate code generation and to improve framework development.
In Python the built-in class type is a metaclass. Consider this simple Python class:

At run time the Car object itself is an instance of the class type. The source code of the class Car shown above contains no such details as the size of Car objects in bytes, their binary layout in memory, the way they are allocated, the automatic call of the __init__ method each time a Car object is created, and so on. These details come into play not only when a new Car object is created, but also every time any attribute of a Car object is accessed. In languages without metaclasses these details are determined by the language specification and cannot be overridden. In Python the metaclass — type — governs these details of Car object behaviour. They can be overridden by using a different metaclass instead of type.
The example above contains redundant code associated with the four attributes make, model, year, and color. Part of this redundancy can be eliminated with a custom metaclass. In Python a metaclass is most easily defined as a subclass of type.

This metaclass overrides only object creation. All other aspects of class and object behaviour are still handled by type.
Now the class Car can be rewritten so that it uses this metaclass. In Python 3 this is done by passing the "keyword argument" metaclass in the class definition:

The resulting Car object can be created as usual, but it may contain any number of named arguments:
new_car : Car = Car ( make = 'Toyota' , model = 'Prius' , year = 2005 , color = 'Green' , engine = 'Hybrid' )
In Smalltalk everything is an object . Moreover, Smalltalk is a class-based system , which means that every object has a class that defines the structure of that object (i.e. the object's instance variables) and the messages the object understands. Taken together, this means that a class in Smalltalk is an object, and consequently a class must be an instance of a class (called a metaclass).
For example, the car object c is an instance of the class Car. In turn, this class Car is also an object and is therefore an instance of a metaclass named Car. Car class Note the space in the metaclass name. The metaclass name is a Smalltalk expression which, when evaluated, yields the metaclass object. Thus evaluating Car class yields the metaclass object for Car, whose name is Car class (this can be confirmed by evaluating Car class name, which returns the name of the metaclass of Car).
Class methods actually belong to the metaclass, just as instance methods actually belong to the class. When the message 2 is sent to an object, the method lookup begins in Integer. If it is not found, the search continues up the chain of superclasses, stopping at Object whether or not it is found.
When a message is sent, Integer the method lookup begins in Integer class and continues up the chain of superclasses to Object class. Note that so far the metaclass inheritance chain exactly follows the class inheritance chain. But the metaclass chain extends further, since Object class is a subclass of Class. All metaclasses are subclasses of Class.
In early versions of Smalltalk there was only one metaclass, named Class`.`. This implied that the methods of all classes were the same, in particular the method for creating new objects, i.e. ` new.`. In order to allow classes to have their own methods and their own instance variables (called class instance variables, not to be confused with class variables ), Smalltalk-80 introduced for each class C its own metaclass ` C class.`. This means that each metaclass is effectively a singleton class .
Since there is no requirement for metaclasses to behave differently, all metaclasses are instances of just one class, called Metaclass. The metaclass of Metaclass is called Metaclass class, which in turn is an instance of the class Metaclass.
In Smalltalk-80 every class (except Object) has a superclass . The abstract superclass of all metaclasses is Class, which describes the general nature of classes.
The superclass hierarchy for metaclasses is analogous to the superclass hierarchy for ordinary classes, with the exception of the class Object. ALL metaclasses are subclasses of Class, therefore:
Like Siamese twins , classes and metaclasses are born together. Metaclass has an instance variable thisClass, which points to its associated class. Note that the ordinary Smalltalk class browser does not display metaclasses as separate classes. Instead, the class browser lets you edit a class together with its metaclass.
The names of the classes in the metaclass hierarchy are easily confused with concepts bearing the same name. For example:
Four classes provide the means for describing new classes. Their inheritance hierarchy (starting from the class Object) and the main capabilities they provide are as follows:
Ruby cleans up the Smalltalk-80 concept of metaclasses by introducing eigenclasses , removing the Metaclass class and (un)redefining the class mapping. The change can be represented schematically as follows:
|
→ |
|
Note in particular the correspondence between Smalltalk's implicit metaclasses and Ruby's eigenclasses of classes. Ruby's eigenclass model makes the concept of implicit metaclasses completely uniform: every object x has its own metaobject, called the eigenclass of x , which is one metalevel above x . «Higher-order» eigenclasses usually exist purely conceptually — they contain no methods and store no (other) data in most Ruby programs.
The following diagrams show the approximate structure of the Smalltalk-80 and Ruby cores for comparison. In both languages the structure consists of a built-in part, which contains cyclic objects (i.e. objects that appear in a cycle formed by a combination of blue or green links), and a user part, which has four explicit objects: the classes A and B and the terminal objects u and v. Green links show the «child→parent» inheritance relationship (with an implicit upward direction), blue links show the «extra member→container» relationship under instantiation (a blue link from x points to the smallest actual container of x , which is the starting point for method lookup when a method is called on x ). Grey nodes represent eigenclasses (respectively, implicit metaclasses in the case of Smalltalk-80).
| Smalltalk-80 | Ruby | |
![]() |
![]() |
The diagram on the right also illustrates the lazy evaluation of eigenclasses in Ruby. The object v may have its eigenclass evaluated (memory allocated) as a result of adding singleton methods to v.
According to Ruby's introspection method named class, the class of every class (and of every eigenclass) is constantly the class Class (denoted c in the diagram). Class and Struct are the only classes that have classes as instances. [ disputed – discuss ] Inheriting from Class is forbidden. Following the standard definition of metaclasses, we may conclude that Class and Struct are the only metaclasses in Ruby. This seems to contradict the correspondence between Ruby and Smalltalk, since in Smalltalk-80 every class has its own metaclass. The discrepancy is based on a mismatch between the class introspection method in Ruby and in Smalltalk. Although the mapping x ↦ x.class coincides on terminal objects, it differs in its restriction to classes. As mentioned above, for a class x the Ruby expression x.class constantly evaluates to Class. In Smalltalk-80, if x is a class, then the expression x class corresponds to the Ruby expression x.singleton_class – which evaluates to the eigenclass of x.
Metaclasses in Objective-C are practically identical to metaclasses in Smalltalk-80 — which is not surprising, since Objective-C borrows a great deal from Smalltalk. As in Smalltalk, in Objective-C the instance variables and methods are defined by the object's class. A class is an object, and consequently it is an instance of a metaclass.
As in Smalltalk, in Objective-C class methods are simply methods invoked on the class object, so class methods have to be defined as instance methods in its metaclass. Since different classes may have different sets of class methods, each class must have its own metaclass. Classes and metaclasses are always created as a pair: the runtime has the functions objc_allocateClassPair() and objc_registerClassPair() for creating and registering class-metaclass pairs respectively.
Metaclasses have no names; however, a pointer to any class object can be denoted using the generic type Class (analogous to the type id used for a pointer to any object).
Since class methods are inherited through inheritance, as in Smalltalk, metaclasses must follow an inheritance scheme analogous to the inheritance scheme of the classes (for example, if the parent class of class A is class B, then the parent class of the metaclass of A is the metaclass of B), with the exception of the root class.
Unlike in Smalltalk, the metaclass of the root class inherits its properties from the root class itself (usually NSObject when using the Cocoa framework ). This guarantees that all class objects are ultimately instances of the root class, so that you can use the root class's instance methods, typically useful helper methods for objects, directly on the class objects themselves.
Since metaclass objects do not behave differently (you cannot add class methods for a metaclass, so all metaclass objects have the same methods), they are all instances of the same class — the metaclass of the root class (unlike in Smalltalk). Thus the metaclass of the root class is an instance of itself. The reason for this is that all metaclasses inherit from the root class; consequently, they must inherit the class methods of the root class.
Herb Sutter of the ISO C++ committee was the first to propose including metaclasses in C++ for C++20 , using the facilities of C++17 . With the adoption of reflection in C++26, this paper was revised.
The main goal is to extend C++'s abstraction beyond a fixed vocabulary ( class, struct, union, enum, etc.) so as to allow the use of an adaptive vocabulary (for example interface, value), for a more liberal approach to programming, free of memorizing rules. This feature would also make it possible to express non-standard facilities (for example interfaces ) as ordinary library facilities and would remove the need for specialized compilers (such as Qt's moc , C++/CX and so on) to express specific information using standardized facilities.
Using code injection (another proposed addition to C++ reflection, which would add injection of a token sequence into the source code) , it would be possible to create a " interface" in the Java/C# style by means of a constevalfunction:

It would also be possible to apply several types of metaclasses. For example, for metaclasses x and y one could write .
class(x, y) MyClass {
/* ... */
};
The paper proposes using abstractions to substantially reduce boilerplate code by producing generated functions and customizable defaults, semantics and constraints. In addition, this removes the need to create new language feature proposals, allowing such features to be expressed by means of metaclass characteristics.
Listed below are some of the most widespread programming languages that support metaclasses.
Less widespread languages that support metaclasses include OpenJava , OpenC++ , OpenAda , CorbaScript , ObjVLisp , Object-Z , MODEL-K , XOTcl and MELDC . Some of these languages appeared in the early 1990s and are of academic interest.
Java's facilities
for introspection , similar to metaclasses but not actually metaclasses.
Logtalk , an object-oriented extension of Prolog , also supports metaclasses.
Both the Resource Description Framework (RDF) and the Unified Modeling Language (UML) support metaclasses.
Metaclasses have been proposed for possible inclusion in a future version of C++ , but are not currently an included feature.
This is an object that governs the behaviour of other objects
Used in:
Example:
__dict____class__Metaobject = a mechanism that influences the behaviour of the system at run time
In computer science, a metaobject is an object that manipulates, creates, describes or implements other objects (including itself). The object to which a metaobject relates is called the base object. The information a metaobject can determine includes the base object's type , interface , class , methods , attributes , parse tree, and so on. Metaobjects are an example of the concept of reflection in computer science , where a system has access (usually at run time) to its own internal structure. Reflection allows a system, in effect, to rewrite itself on the fly, to change its own implementation as it runs
A metaobject protocol ( MOP ) provides a vocabulary ( a protocol ) for accessing and manipulating the structure and behaviour of object systems. Typical functions of a metaobject protocol include:
The metaobject protocol runs counter to Bertrand Meyer's open/closed principle , which states that software object systems should be open to extension but closed to modification . This principle in effect distinguishes between extending an object by adding to it and modifying an object by redefining it, assuming that the former is a desirable quality («objects should be extensible to meet the requirements of future use cases»), while the latter is undesirable («objects should provide a stable interface not subject to summary rework»). The metaobject protocol, by contrast, transparently exposes the internal structure of objects and of the entire object system from the point of view of the system itself. In practice this means that programmers can use objects to redefine themselves, possibly in rather complex ways.
Moreover, a metaobject protocol is not merely an interface to an «underlying» implementation; rather, by means of the metaobject protocol the object system is recursively implemented through a metaobject system, which in turn is theoretically implemented through a meta-metaobject system, and so on, until some arbitrary base case is defined (a consistent state of the object system), with the protocol itself constituting a recursive functional relationship between these implementation levels.
Implementing object systems in this way opens up the possibility of radical arbitrary redesign, providing great flexibility but introducing potentially complex or hard-to-understand metastability problems (for example, an object system must not destructively update its own metaobject protocol — its internal self-representation — but the potential destructiveness of some updates is nontrivial to predict and may be hard to reason about), depending on the depth of recursion to which the desired modifications propagate. For this reason a metaobject protocol, if present in a language, is usually used sparingly and for specialized purposes, such as software that transforms other software or itself in complex ways, for example in reverse engineering.
When compilation is not available at run time, additional difficulties arise in implementing a metaobject protocol. For example, with such a protocol one can change the type hierarchy, but this may cause problems for code compiled with an alternative definition of the class model. In some environments innovative solutions to this problem have been found, for instance by handling metaobject issues at compile time. A good example is OpenC++ . The object-oriented semantic web model is more dynamic than most standard object systems and is consistent with run-time metaobject protocols. For example, in the semantic web model classes are expected to change their relationships with one another, and there is a special inference mechanism, known as a classifier, that can check and analyse evolving class models.
The first metaobject protocol was developed in the object-oriented programming language Smalltalk , created at Xerox PARC . The Common Lisp Object System (CLOS) came later and was influenced by the Smalltalk protocol, as well as by Brian C. Smith's original research on 3-Lisp as an infinite tower of evaluators. The CLOS model, unlike the Smalltalk model, allows a class to have more than one superclass ; this creates additional complexity in such matters as resolving the ancestry of the class hierarchy on some object instance. CLOS also permits dynamic multimethod dispatch, which is handled by generic functions rather than by message passing as in Smalltalk's single-method dispatch . The most influential book describing the semantics and implementation of the metaobject protocol in Common Lisp is «The Art of the Metaobject Protocol» by Gregor Kiczales et al.
Metaobject protocols are also widely used in software engineering applications. In virtually all commercial CASE environments, reengineering environments and integrated development environments there is some form of metaobject protocol for representing and manipulating design artifacts.
The metaobject protocol is one way of implementing aspect-oriented programming . Many of the early founders of MOP, including Gregor Kiczales , subsequently became leading proponents of aspect-oriented programming. Kiczales and his colleagues at PARC were engaged to develop AspectJ for Java , a language that has no metaobject protocol of its own.
Comments