Content deleted Content added
→The primary structure: Made a section instead of subsection. Example added. |
m WP:CHECKWIKI error fix #38. Convert HTML to wikicode. Do general fixes and cleanup if needed, typos fixed: , → , using AWB (8686) |
||
Line 3:
{{TOC right|limit=3|width=30ex}}
__TOC__
In [[object-oriented programming|object-oriented]] [[Computer programming|programming]], the '''eigenclass model''' is an [[abstract structure]]
{{efn|
In the wider sense,
the eigenclass model is an [[
– a system of structures together with transitions
between them.
It can be considered the most abstract non-trivial ASM of object-oriented programming.
}}
that constitutes a fundamental part of the [[object model]] using the concept of
Eigenclasses are auxiliary (mostly just fictitious) class-like objects that establish [[infinite regress]] via the eigenclass
[[
for every object
the unique own meta-object of
As a complementary constituent to the eigenclass map, the model encompasses the [[
The composition of the eigenclass map with inheritance gives rise to
a relation between objects, denoted
.<ref name="ome">{{cite web | url=http://www.atalon.cz/om/object-membership/ | title=Object Membership: The core structure of object-oriented programming }}</ref>
This relation is a generalization of the
and can be viewed as a
[[Non-well-
[[set membership]],
As a result, the eigenclass model provides a uniform and
Line 45 ⟶ 44:
== History ==
The inception of the eigenclass model with referenceable eigenclasses can be attributed to [[Smalltalk (programming language)|Smalltalk-80]] which introduced
In Smalltalk, every class has its own metaclass, and metaclass inheritance parallels class inheritance.
However, a full and consistent application of the eigenclass model appeared first (and only) in the
[[Ruby (programming language)|Ruby programming language]].
The term
(although in Ruby 1.9, the corresponding introspection method is still named <code>singleton_class</code>).
Line 56 ⟶ 55:
In its rudimentary form, the eigenclass model can be described
as a canonical structure
with subsequently introduced notation, terminology and axioms.
For convenience, an example structure is provided first.
Line 63 ⟶ 62:
The following diagram shows an example of the canonical structure
together with corresponding Python code.
Line 88 ⟶ 87:
The structure contains 6 [[#Primary_objects|primary objects]]:
2 [[#Helix|helix]] classes
(the [[#Inheritance_root|inheritance root]]
3 other [[#Classes|classes]] (<code>M</code>, <code>A</code> and <code>B</code>),
and 1 [[#Terminal_objects|terminal object]] (<code>b</code>).
Right-directed arrows (in gray) show the eigenclass map,
up-directed arrows (in green) show the child-parent relation of [[#Inheritance|inheritance]].
The <i style="color:green">
[[#Eigenclasses|Eigenclasses]] are shown as unnamed nodes in gray.
Each eigenclass chain is infinite – the diagram displays just an initial part, without descendants of the fourth eigenclass of
The structure contains 2 explicit [[#Metaclasses|metaclasses]]:
the metaclass root
The remaining inheritance descendants of
(i.e. all eigenclasses except the eigenclass of <code>b</code>) are implicit metaclasses.
=== Objects ===
The universum of the model is the set
By further axioms, this set is asserted to be [[countably infinite]].
=== Object membership ===
The
For objects
then
By axiom (1), object membership is uniquely decomposable into the eigenclass map and the inheritance relation, which can be written as
:(ϵ) = (
where the composition symbol '
i.e.
=== Inheritance ===
The
defined by
:
Axiom (2) asserts antisymmetry of
Furthermore, axiom (1) asserts that
<span style="white-space:nowrap">(
:
which indicates that the inheritance relation,
If
For an object
Similarly, for a set
Direct ancestors ([[Covering relation|covers]]) of
<!-- and denoted
=== Eigenclasses ===
The
is the container of
Axiom (1) asserts that every object has its eigenclass.
Furthermore, (1) and (2) imply that the
In particular,
Another consequence of (1) is that for every objects
:
showing that the eigenclass map
corresponds to the [[powerset]] operator.
The
By further axioms, each component of the eigenclass map is an infinite chain
An
=== Primary objects ===
Objects that are not eigenclasses are
Axiom (6) asserts that the set of all primary objects forms a closure system in inheritance, i.e. the set appears as the image of a (necessarily unique) [[closure operator]], denoted
For each object
least primary ancestor of
Axiom (7) asserts that
As a consequence,
[[Homomorphism#Homomorphisms_of_relational_structures|homomorphic]]
[[
of <span style="white-space:nowrap">
onto the [[#Primary_structure|primary structure]],
<span style="white-space:nowrap">
Primary objects are further divided into
:
=== Classes ===
An object is a
and either is its own member or is not maximal in inheritance
(i.e. has parents).
The set of classes is denoted
Classes together with eigenclasses form the set of all descendants
of the inheritance root
i.e.
Using the [[#is-a|is-a]] naming convention, this set is equal to the set of <code style="color:#700000">Class</code>es, where <code style="color:#700000">Class</code> is the name for the instance root
=== Terminal objects ===
An object is
The set of terminals is denoted
Therefore, the set of objects is a disjoint union of the sets of
terminals, classes and eigenclasses:
:
Terminals can be equivalently characterized as objects that are both maximal and minimal in inheritance.
Line 214 ⟶ 213:
250px
]]
The
Axiom (6) asserts that
Equivalently, the
As a consequence,
Axiom (8) asserts that the
– the
The diagram on the right shows the class map for the [[#Example|example]] structure, in the restriction to primary objects.
To illustrate the
=== Instance of ===
The
:
The relation can be expressed as (
The
:
The direct-instance-of, instance-of and member-of relations form an inclusion chain:
:(
=== {{anchor|is-a}} Membership as is-a ===
If
(in particular, if
The set of all members of <code style="color:#700000">B</code> (instances of the <code style="color:#700000">B</code> class) can be referred to as <code style="color:#700000">B</code>s.
If <code style="color:#700000">A</code> and <code style="color:#700000">B</code> are classes such that
<code style="color:#700000">A</code>
:an <code style="color:#700000">A</code> is a <code style="color:#700000">B</code>,
Line 262 ⟶ 261:
=== Helix ===
An object
i.e.
The set of all helix objects is denoted
Axiom (4)(c) asserts that
The helix has the inheritance root,
Eigenclass chains are parallel to the helix axis.
Each complete turn away from the origin corresponds to one application of the eigenclass map.
Line 272 ⟶ 271:
==== Inheritance root ====
The
Its existence is asserted by axiom (4)(a).
==== Instance root ====
The
It can also be specified as
Axiom (4)(b) asserts that
==== Twist links ====
The child-parent pair
Axiom (4)(d) asserts that
In addition, it is asserted that
The same conditions hold for all twist links
=== Metaclasses ===
An object is a
the set of all metaclasses is simply expressed as
The instance root
Metaclasses are either
An object is an implicit metaclass iff it is an eigenclass of a non-terminal object.
Under the assumption that every class has a direct instance, i.e.
:
i.e. an object is a metaclass if it is either the class of an eigenclass or the eigenclass of a class or the eigenclass of an eigenclass.
Using axiom (7) and substituting
:
i.e. aside from higher-order eigenclasses, explicit metaclasses are
The classical definition of metaclasses as "
<ref>{{cite book|author=Ira R. Forman and Scott Danforth|title=Putting Metaclasses to Work|year=1999|isbn=0-201-43305-2}}</ref>
applies as follows:
Line 316 ⟶ 315:
This definition is valid if and only if each class that is not a metaclass has at least one terminal instance, i.e.
<span style="white-space:nowrap">
(in particular, the parent of
=== Axioms ===
The canonical structure
<ol style="list-style-type:none; margin-left: 2ex;">
<li style="text-indent:-3ex; margin-left:3ex;">(1)
Containers of an object
ancestors the eigenclass of
i.e.
:(ϵ) = (
<li>(2)
Line 343 ⟶ 342:
<li>(a)
All non-terminal objects are descendants of a single object,
the inheritance root
<li>(b)
The eigenclass of
<li>(c)
The set
<li>(d)
For every
<li>(e)
Every helix descendant of
</ol>
Line 363 ⟶ 362:
<li>(6)
Every object
<li>(7)
For every object
<li style="text-indent:-3ex; margin-left:3ex;">(8)
There is a helix object
are disjoint.
<!--
<li>(8)
There is a helix object
-->
Line 390 ⟶ 389:
</ol>
Axiom (7) can be expressed without a reference to the
== The primary structure {{anchor|Primary_structure}} ==
Line 398 ⟶ 397:
The restriction of a canonical structure of object membership
to primary objects can be expressed as a structure
<span style="white-space:nowrap">
where
<ul>
<li>
<li>
<li>
</ul>
such that
all helix classes are among ancestors of
<!-- -->
The structure is subject to the following axioms:
Line 421 ⟶ 420:
<li style="text-indent:-3ex; margin-left:3ex;">(p~1)
(
<li>(p~2) Inheritance
<li>(p~3)
Line 433 ⟶ 432:
<li>(p~5) Metaclasses cannot have terminal instances.
<li>(p~6) Every object
<li>(p~7) Cycles in
<li>(p~8) The set of primary objects is finite.
Line 450 ⟶ 449:
The diagram on the right shows the primary structure that is the restriction of the [[#Example|example]] structure.
The instance-of relation is obtained as the composition
<span style="white-space:nowrap">(
– the "non-inherited" part of the
(displayed by dark blue arrows).
=== Eigenclass completion ===
Line 464 ⟶ 462:
<li>(5')
Descendants of eigenclasses-other-than-
</ol>
Assuming (5'), the object membership structure,
<span style="white-space:nowrap">
is uniquely determined by the primary structure,
<span style="white-space:nowrap">
up to isomorphism.
(Therefore,
<span style="white-space:nowrap">
<span style="white-space:nowrap">
Given a structure
<span style="white-space:nowrap">
the
<span style="white-space:nowrap">
<ol>
Line 486 ⟶ 484:
Equip each primary object with an eigenclass chain
such that distinct primary objects have disjoint eigenclass chains.
Let the
<li>
Extend
Let
<ol style="list-style-type: upper-alpha">
<li>
where
<li>
<li>
</ol>
<li>
Extend
</ol>
Line 522 ⟶ 520:
<ol>
<li>
Generalize the canonical structure
[[
<li>
Line 537 ⟶ 535:
==== Canonical reduct ====
The canonical reduct
.<ref name="ruby-s1">{{cite web | url=http://www.atalon.cz/rb-om/ruby-object-model/rb-om-s1.pdf | title=Ruby Object Model – The S1 structure }}</ref>
In particular, the structure only allows single inheritance so that
except for
The order-embedding property of
In addition, Ruby disallows explicit metaclasses other than
As of Ruby 1.9, there are exactly 4 helix classes:
:
==== Module inclusion ====
The "full" membership,
<code style="color:#700000">Module</code> class,
i.e. modules are <code style="color:#700000">Module</code>s
that are not <code style="color:#700000">Class</code>es.
The additional structure is given by the
If <u>
the
: (ϵ') = (ϵ) ○ <u>Μ</u>.
This extended membership corresponds to the <code>is_a?</code> introspection method which is aliased by <code>kind_of?</code>.
Similarly, the "superclass" inheritance,
: (≤') = (≤) ○ <u>Μ</u>,
which, in the restriction to <code style="color:#700000">Module</code>s, corresponds to the <code><=</code> introspection method.
This extended inheritance is a
In addition, since Ruby supports dynamic module inclusion,
.<ref>{{cite web | url=http://web.archive.org/web/20101113235808/http://eigenclass.org/hiki/The+double+inclusion+problem | title=The double inclusion problem }}</ref>
=== In Python ===
Line 577 ⟶ 575:
There are exactly 2 helix classes:
:
No additional constraints are imposed.
Line 583 ⟶ 581:
=== In Scala and Java ===
In Scala and Java, classes form actually a
This subset can be expressed as
where
This way the set
In Scala, mixins are called
in Java they are
Mixins are not allowed to be metaclasses.
The structure is then subject to additional constraints.
There are no explicit metaclasses other than
and, more importantly, a single inheritance between classes applies
(but not between traits / interfaces).
The helix contains 3 classes:
:
For Java, the <code>Any</code> class can be thought of as a fictitious root allowing primitive values to be objects
– they become objects that are not <code style="color:#700000">Object</code>s.
Mixins (traits / interfaces) are among descendants of the <code>Object</code> class.
Java in addition disallows interleaving interfaces with classes, so that
=== In Smalltalk-80 ===
To describe the eigenclass model as it applies to Smalltalk, one has to make several assumptions about possible program states
<!-- -->
As a consequence, the model does not capture all the anomalies allowed by [[Pharo]] or [[Squeak]], the major Smalltalk-80 implementations.
These ruled-out anomalies include in particular cycles in the inheritance relation (established via the <code>superclass:</code> method), "dangling metaclasses" (created by <code style="white-space:nowrap">Metaclass new</code>), and subclasses of the <code>Class</code> class.
There are two features of the Smalltalk object model that do not conform to the canonical structure
Metaclass redirection is expressed via an imposed metaclass subroot,
named <code>Metaclass</code>, which induces the corresponding
This map coincides with the standard
map except for implicit metaclasses, where it "redirects" the value from the <code>Class</code> class to the <code>Metaclass</code> class, introducing monotonicity breaks with respect to inheritance.
Additional twist links are child-parent pairs
Each of Pharo and Squeak contain one such class, named <code>PseudoContext</code> and <code>ObjectTracer</code>, respectively.
The helix chain contains 5 classes:
:
The <code>Metaclass</code> class is a sibling of the <code>Class</code> class.
Finally, the Ruby-like conditions apply: There are no explicit metaclasses other than
==== {{anchor|smalltalk-traits}} Traits ====
Similarly to Ruby module inclusion, Smalltalk-80 supports extension of inheritance via inclusion of terminal objects, called
.<ref name="traits">{{cite web | author=Nathanael Schärli | url=http://scg.unibe.ch/archive/phd/schaerli-phd.pdf | title=Traits: Composing Classes from Behavioral Building Blocks}}</ref>
Traits are <code style="color:#700000">Trait</code>s – instances of the built-in <code style="color:#700000">Trait</code> class.
Unlike in Ruby, the semantics of extended object membership,
=== In Objective-C ===
Line 639 ⟶ 637:
In Objective-C, the eigenclass model has to be generalized to allow multiplicity and degeneracy of inheritance roots.
There are several components of object membership, each with its own inheritance root.
In each component, the inheritance root
As a consequence, metaclasses have to be defined as objects that are either equal to an inheritance root or are descendants of the eigenclass of an inheritance root (this definition also applies to the canonical structure).
Line 648 ⟶ 646:
The Common Lisp Object System deviates from the canonical structure in two features.
It introduces non-linear inheritance between helix classes as well as an
Unlike in Smalltalk, this imposed class map cannot be expressed via a constant "redirection" target.
As of [[CLISP]] 2.49, there are 8 helix classes:
:
The missing 4 classes do not form a chain in inheritance.
Line 660 ⟶ 658:
The Perl object model is distinguished by total circularity of classes: Every class is the class of itself. As a consequence, the instance-of relation, in its restriction to classes, coincides with the inheritance relation (so that there is no disambiguity in the interpretation of [[#is-a|is-a]]).
Every class is an instance root – so that there is an
There is a single built-in inheritance-root, named <code>UNIVERSAL</code> (however, this statement requires the assumption that the <code>@ISA</code> variable of this class is not changed).
Line 671 ⟶ 669:
Actual objects comprise all primary objects (terminals and classes) plus some eigenclasses.
Except for Ruby, eigenclasses of eigenclasses (elements of
Even in Ruby, manipulating these higher-order eigenclasses did not find any practical use
.<ref>{{cite book | publisher=Pragmatic Bookshelf | author=Paolo Perrotta | url=http://pragprog.com/book/ppmetr/metaprogramming-ruby | title=Metaprogramming Ruby | isbn=978-1-934356-47-0}}</ref>
=== {{anchor|actuality-axioms}} Axioms ===
A canonical structure of object membership with
<!-- -->
Objects from
The structure is subject to the following conditions:
Line 692 ⟶ 690:
<li>(a~3)
For every object
<li style="text-indent:-5ex; margin-left:5ex;">(a~4)
The
<li style="text-indent:-5ex; margin-left:5ex;">(a~5)
For some (necessarily unique)
</ol>
Line 707 ⟶ 705:
=== Actualclass map ===
The
Equivalently, for an object
is the least container of
The actualclass map goes between the eigenclass map and the class map, i.e. for every object
:
The
Similarly to the
The root equals
=== Specializations ===
Line 723 ⟶ 721:
In Python, Java, CLOS, and Perl, eigenclasses are purely fictitious – they are never actual, so that the actualclass map coincides with the class map.
Scala allows eigenclasses of terminal objects, e.g. via the <code>object</code> definition
.<ref>{{cite book | publisher=Artima Press | author=Martin Odersky, Lex Spoon, Bill Venners | url=http://www.artima.com/shop/programming_in_scala_2ed | title=Programming in Scala | isbn=978-0-9815316-4-9}}</ref>
In Smalltalk-80 and Objective-C, the set of actual eigenclasses equals
==== In Ruby ====
In Ruby, all objects that are not
<ref name="rb-om">{{cite web | url=http://www.atalon.cz/rb-om/ruby-object-model/ | title=The Ruby Object Model: Data structure in detail}}</ref> can have actual eigenclasses.
As of [[
Ruby is the only language (at least of the above mentioned ones) that supports dynamic eigenclass allocation. Typically, for an object
<!-- -->
Moreover, Ruby in fact maintains 2 actuality extents, i.e. two different sets of actual objects.
The first set is the set of actually
The actualclass map for the larger set corresponds to the <code>klass</code> field in the [[
==== In Smalltalk-80 ====
In Smalltalk, the imposed class map has the corresponding
Due to the metaclass redirection, the imposed actualclass map does not form a tree but just a (directed) [[pseudotree]] with a 2-element cycle containing the <code>Metaclass</code> class and its eigenclass
.<ref>{{cite book | publisher=Springer Verlag | author=John Hunt | url=http://stephane.ducasse.free.fr/FreeBooks/STandOO/Smalltalk-and-OO.pdf | title=Smalltalk and Object Orientation: An Introduction | isbn=978-3540761150}}</ref>
== Name resolution ==
Object membership,
Similarly to [[
There are two basic interpretations of the source: as
Owner-arrows are explicit data bindings: a target value is bound to an owner object under a name.
Receiver-arrows are implicit: an object receives (inherits) a named property from an appropriate owner via
The process of finding an owner-arrow for a given receiver and name is an essential part of
There are two main ways how to interpret
In the
For class-based programming languages, this mode is of minor importance and is usually unsupported. In Ruby, it occurs in
In the
This is the primary mode, used in particular for finding arrows that point to methods, (a part of) the process known as
Since containers of an object are just ancestors of the object's eigenclass, method lookup can be thought of as a two-stage process: first step to the eigenclass, then look up in ancestors.
In Ruby, this is expressed as a "method call mantra"
Line 771 ⟶ 769:
=== Conflict resolution ===
In the ideal case, objects that are owners of an
If
In the general case, an object can have
There are 3 main ways how to either avoid or resolve such conflicts:
Line 785 ⟶ 783:
Disallow conflicts by enforcing additional arrows.
Upon object creation (in particular, class creation),
if a conflict is detected for a name
make sure that the new object itself becomes an owner of an
This solution is used in Smalltalk-80 by the [[#smalltalk-traits|traits]] mechanism.
<li>
Maintain additional ordering so that a
This applies to Ruby, Scala, Python, CLOS and Perl.
</ol>
Line 798 ⟶ 795:
=== Linearization ===
The
denoted
that determines the order in which ancestors are looked up for
ownership of a property (binding) with a given name.
For every
The
This structure can be conveniently termed
As a result of linearization, MRO is a forest: every element
Starting at
The [[
In Ruby, this is exactly the self-or-own-includer-of relation, <u>
In Scala, the MRO ___domain is a similar relation between
<code style="color:#700000">Class</code>es (classes, eigenclasses, traits) and traits.
In Python, Perl and CLOS, there is no distinction of mixins like in Ruby or Scala, so that the MRO ___domain equals the inheritance – it contains all pairs
== Transitions ==
Standard [[State transition system|transitions]] are those of new "user" object creation. The structure is modified by adding a primary object
Except for languages with degenerated metaclass roots, new object
: <code>
where
In practice, creation of terminal objects
(where
is syntactically differentiated from creation of classes
(where
{{efn|
However, Ruby also supports the uniform expression:
<code>Class.new(A)</code> creates a new subclass of <code>A</code>.
}}.
In Perl, the pattern is not applicable to class creation due to the [[
In Objective-C, if
Similarly, the pattern is not applicable to the helix structure, which is built-in and cannot be changed by transitions.
Line 840 ⟶ 837:
Dynamic class creation is provided as a secondary option.
In Ruby, transitions of the extended structure
<u>
Some languages support transitions such that the old structure is not a [[substructure]] of the new one.
|