As a result, the document provides a uniform and consistent view of an essential part of the foundations of object oriented programming.
Author
|
Document date
|
Note: For a more detailed introduction into the subject see [].
fundamental partwe mean a structure that encompasses the following fundamental relations:
The goal is to introduce a common mathematical structure such that for most class-based languages, there is a correspondent part of the data model that forms a special case. Such a common mathematical structure would provide a uniform and consistent view of foundations of OOP.
To specify the universe on which the structure is defined, we follow the well-known OOP guideline:
Any
, Object
, Class
, Int
and i
.
|
green links.
dark blue links(the class map) with the inheritance.
var Any = classOf[Any] var Object = classOf[Object] var Class = classOf[Class[_]] var Int = classOf[Int] var i = 7 assert (Object.isAssignableFrom(Class)) assert(!Object.isAssignableFrom(Int)) assert ( Class.isInstanceOf [Object]) assert ( Int.isInstanceOf [Object]) assert ( i.isInstanceOf [Int]) assert ( i.isInstanceOf [Any]) //assert( !i.isInstanceOf [Object]) // not supported assert (i.getClass == Int) assert (i.getClass.getClass == Class) println (if (Object == Any) "???" else "OK") // ???The code also shows that in Scala, there is some indirection in support of the
Everything is an objectpattern. In particular:
receiverobject a and a name s the task is to determine the value of the possibly inherited property of a
named(by) s. As a subtask, the
ownerobject y has to be determined that interprets s – i.e. y is an object that
ownsan s-named binding to the requested target value. In a simplified form, the subtask is performed in two steps:
own) an s-named binding.
unresolved.
A::B
.
Note: Setting x = a is exactly what is performed in languages with prototypal inheritance, e.g. JavaScript.
a.b
.
In step (2), if we denote y = x.owner(s) then for each
name s, the .owner(s) map is a partial
closure operator
in inheritance.
(By partial
we mean a restriction to the set
of objects that have an ancestor with an s-named binding.)
However, the existence of such an operator is only guaranteed for
single inheritance
– i.e. when the inheritance relation is a forest.
In general, additional structure is required that equips every ancestor set
with a linear order.
frontsubstructure can have an in-memory representation, so that eigenclasses are mostly fictitious:
object
construct)
have a referenceable eigenclass.
The second, more serious, problem consists in the requirement that metaclasses are classes. Consider the following Ruby code:
class A; end p A.class # Class (class B < Class; end) rescue p $! #... can't make subclass of ClassUsing the (b) definition, we could conclude that in Ruby, there is one and only one metaclass: the
Class
class.
However, since the
Ruby object model is in tight correspondence with the Smalltalk-80 object model
(regarding the instance–inheritance structure)
we would obtain the following paradox:
Class
class, Smalltalk has no metaclasses.
(∗)
We provide a solution to the above problems by proposing a new definition of a metaclass:
inheritance descendantis meant in the non-strict sense – including the metaclass root itself. Metaclasses that are (resp. are not) classes are called explicit (resp. implicit). The paradox (∗) then turns into the statement that except for the
Class
class, Smalltalk has no explicit metaclasses.
The definition applies directly to all of Ruby, Python, Scala, Java, Smalltalk
and CLOS,
although in the case of the latter two languages care must be taken as to what
is meant by class of
in (2).
Unfortunately, the introspection methods class
(in Smalltalk)
and class-of
(in CLOS) are misleading here.
For Objective-C and Perl we have to use a modified definition due to the multiplicity and degeneracy of metaclass roots:
Ruby | Python | Smalltalk | Objective-C | Scala | Java | CLOS | Perl | |||
S1 | Explicit metaclasses | ● | ● | ○ | ||||||
Implicit metaclasses | ● | ● | ● | |||||||
Eigenclasses of terminal objects | ● | ● | ||||||||
Eigenclasses of eigenclasses | ● | |||||||||
Multiple inheritance | ○ | ● | ○ | ◐ | ● | ● | ||||
Terminal mixins | ● | ● | ||||||||
Non-terminal mixins | ● | |||||||||
Multiple roots | ○ | ● | ||||||||
Degenerated root(s) | ● | ● | ||||||||
Additional twist links | ● | |||||||||
Imposed class map | ● | ● | ||||||||
Non-linear helix | ● | |||||||||
Circular classes | ● | |||||||||
Described by structure | S1r | S1p | S1m+w+r | S1c | S1s | S1ℓ | S1@ | |||
S2 | Linearization | ● | ● | ● | ● | ● | ||||
Described by structure | S2r | S2p | S1m+w+r | S1c | S2s | S1s | S2ℓ | S2@ |
Notes:
explicit metaclasseshere we mean explicit metaclasses other than metaclass root(s). For Python and CLOS it also means support for user-created explicit metaclasses. The ○ symbol for Perl indicates that Perl's classes become metaclasses by universal circularity.
terminal mixinswe mean Ruby modules or Smalltalk traits. These are terminal objects that are indirectly involved in inheritance – in particular, being terminal objects, they are NOT descendants of the inheritance root.
non-terminal mixinswe mean Java interfaces or Scala traits. These class-like objects are distinct from classes but are directly involved in inheritance – in particular, they are descendants of the inheritance root.
Multiple rootsmeans that there can be more that one class without inheritance parent(s). The ○ symbol for Smalltalk indicates that in Smalltalk-80 (as implemented by Pharo or Squeak), there are multiple classes without ancestors but only a single
mainroot. The
subsidiaryroots arise from additional twist links.
degenerated rootwe mean an inheritance root that is its own class. (Equivalently, it is an inheritance root that is a parent of its eigenclass.)
imposed class mapfeature can be equivalently characterized as a support for a class map with monotonicity breaks w.r.t. inheritance. That is, it is possible that for some objects x, y, x is a descendant of y but the class of x is not a descendant of the class of y.
Non-linear helixmeans that there is multiple inheritance (even) between helix classes (ancestors of the metaclass root).
circular classesfeature means that in addition to helix classes there are other classes that are its own instances.
pointedobject membership, (Θ, ϵ, m).
Ruby | Python | Smalltalk | Objective-C | Scala | Java | CLOS | Perl | |
Implementation platform | MRI | CPython | Pharo | GNUStep | JRE | CLISP | Strawberry | |
Version | 1.9.2 | 3.2.2 | 1.3 | 0.29.1 | 2.10.0 | 1.7.0 | 2.49 | 5.16.1 |
An S1p structure is a structure (O, .ec, .pr, ≤, r, c) where
(O, .ec, .pr) is a primorder algebra.
We will apply established notation and terminology, in particular, definition of .ce and .eci. | |
The inheritance ≤
is a partial order on O such that
| |
For every objects x, y,
| |
For helix objects, the following holds:
| |
For every class x and every eigenclass e,
| |
The set O.pr of primary objects forms a closure system in
the inheritance ≤.
Let .c denote the corresponding closure operator, i.e. for a non-terminal object x, x.c is the least class y such that x ≤ y. (For a terminal x, x.c = x.) Let .class denote the composition .ec.c (and .class(i) its i-th application, i ≥ 0). | |
For every object x,
| |
For every non-helix class x and every i > 0,
| |
The set C of classes is finite. |
side view.
Full structure | Restriction to primary objects | ||
Inheritance | Instance tree | ||
|
|
|
M
< r.ec(2).
|
Corresponding Python code:class M(type): pass class N(type, metaclass=M): pass class A(metaclass=N): pass class B(A): pass b = B() |
b
.ec < r.ec
A
.ec < b
.ec
b
.ec(1) < b
.ec(2)
A
< c
B
< A
.ec
←
¬
B .class is undefined
class M(type): pass class N(type): pass class A(metaclass=M): pass # metaclass conflict class B(A,metaclass=N): pass |
B
.class is undefined
A
.class.class ≠ A
.ec.class
N
.class.class ≠ N
.ec.class
N
.class.class ≠ N
.ec.class
M
.ec < M
M
.ec < M
M
.ec(2) < M
Proposition:
(1) |
For every objects x, y,
|
(2) |
For every objects x, y,
|
(3) | An object is terminal if it is both maximal and minimal in ≤. |
(4) | The inheritance root r is the unique object that is maximal in ≤ but not minimal. |
Corollary: An S1p structure is fully determined by the ϵ relation.
Note: In the sequel we provide alternative axiomatization of S1p structures based on the ϵ relation.
X
are referred to as X
s.
An instance of X
is said to be an X
.
Observations:
Class
is the name of the metaclass root c then
Class
es
is synonymous to non-terminal objects(i.e. classes and eigenclasses).
Notation | Composition | Terminology | y restricted to |
ϵ• | (ϵ) ○ (Μ) | x kind-of y | |
ϵ | (.ec) ○ (≤) | x member-of y | C, O.ec |
(ϵ) ○ (.c) | x instance-of y | C | |
.class | (.ec) ○ (.c) | x direct-instance-of y (the class of x is y) |
C |
Proposition A:
(1) |
Assuming just
| ||||
(2) |
For every object x,
| ||||
(3) |
For every object x,
| ||||
(3') |
For every object x and every i ≥ 0,
| ||||
(4) |
Let x, y be objects such that
x ∈ H iff y ∈ H. Then
| ||||
(5) | The inheritance ≤ is upper finite, i.e. every object has finite number of ancestors. | ||||
(6) | Every non-helix eigenclass chain is an antichain in inheritance. | ||||
(7) | The set of helix objects forms an up-set in inheritance. (I.e. if x < y and x is a helix object then so is y.) | ||||
(8) | The set of non-helix eigenclasses forms a down-set in inheritance. | ||||
(9) |
Let ≲ be a relation between primary objects defined by
|
Proposition B:
Assume just
(i) |
|
(ii) |
The .class map forms a tree such that c
is the root.
Equivalently, for every class x,
|
(ii') |
For every class x and every i ≥ 0,
|
(iii) |
The following is satisfied:
|
(iv) |
For some helix object h,
|
Proof:
(i)→(ii')
We first show that
Let x.class(i) = x for some i > 0.
Since x.class(i) = x.ec(i).c
we have x.ec(i) < x, thus x must be a helix class.
But x.class = c for every helix class so that x = c.
(ii')→(i)
Assume x.ec(i) < x for some class x and i > 0.
Denote y = x.ec(i).c.
Then
Proposition:
Proposition:
Observations:
Note:
In the eigenclass alignment
used before,
terminals are drawn in the same column
as the inheritance root r.
This alignment is motivated by the situation when
all descendants of r.ec are eigenclasses
(i.e. there are no explicit metaclasses other than c)
as is the case in Ruby.
Each column then contains objects x with the same eigenclass index
x.eci.
class A: pass class M(A,type): pass |
class M(type): pass class N(M,metaclass=M): pass assert N.__class__ == M |
metalevel separation condition.
For every non-helix objects x, y,
|
Proposition A:
Proposition B:
Assume that
the metalevel separation condition
Note: The explicit/implicit terminology is redundant. We could use the primary/secondary terminology established in the 2x2 nomenclature of objects. [].
M
and N
.
Observations:
Proposition:
Corollary: Up to isomorphism, an S1p structure is uniquely given by (O.pr ∪ H, .pr, ≤, .class).
For every class x and every (helix) eigenclass e,
|
Proposition A: The following conditions are equivalent:
Proposition B:
Assume that
Corollary:
Note: A standalone axiomatization of (O.pr, ϵ, ≤) / (O.pr, .class, ≤) is provided in a specialized section.
Proposition:
x = q.new(p1,…,pn)
In the following Ruby code,
new primary objects A
and a
are created.
A
is a class such that A
.class = c and
A
.parents = {Object
}.
a
is a terminal object such that
a
.class = A
and
(necessarily) A
.parents = ∅.
class Object alias ec singleton_class end c = Class # c refers to Class, the only explicit metaclass in Ruby A = c.new(Object) # A is a new class - a subclass of Object a = A.new # a is a new terminal - a direct instance of A c.new(c) rescue puts $!.message # can't make subclass of Class c.new(A.ec) rescue puts $!.message # can't make subclass of singleton class A.ec.new rescue puts $!.message # can't create instance of singleton class a.new rescue puts $!.message # undefined method `new' for #<A:0x8b48e0>The last 4 lines show rejected transition requests. Neither c nor the eigenclass
A
.ec
can be inheritance parents of a class.
Neither A
.ec nor a
can have instances.
By an S1ϵ structure we mean a structure (O, ϵ) where
Every object x has a unique smallest container,
called the eigenclass of x, denoted x.ec,
whose all ancestors are containers of x, i.e.
| |
Distinct objects have distinct sets of containers, i.e.
for every objects x, y,
| |
Terminals are minimal in inheritance, i.e.
for every objects x, y,
| |
Helix objects satisfy the following properties:
| |
Descendants of non-helix eigenclasses are eigenclasses, i.e.
for every objects x, y,
| |
Primary objects form a closure system in the inheritance, equivalently,
for every object x there is a unique object, denoted x.class,
such that
| |
For every object x,
| |
Helix ancestors of descendants of non-helix classes are lower bounded, i.e.
there exists a helix object h such that
for every non-helix class x,
| |
The following finiteness conditions are satisfied:
|
An eigenclass different from r.ec can only have eigenclasses as descendants. |
Proposition:
For every object x,
|
(1) |
Proof:
The implication
x ϵ y.ec → x ≤ y
is shown by the diagram on the right.
Assume | ||||
(2) |
Terminal objects have no members.
Proof:
Assume that x ϵ t for a terminal t.
Then x.ec ≤ t, thus,
by | ||||
(3) |
An object x is a helix class iff r.ec < x.
Proof:
Let r.ec < x.
Since x is not minimal it cannot be terminal.
The implication
r.ec < y.ec → r < y
shows that x cannot be an eigenclass.
Thus x is a class. In particular, x ≤ r.
As a consequence, x.ec ≤ r.ec < x so that
| ||||
(4) |
The inheritance root, r, is a helix class.
Proof:
Follows by (3) and | ||||
(5) |
There is a least helix class, the instance root c,
equal to r.class.
In addition, c ≠ r.
Proof:
Follows by (3) and | ||||
(6) |
The sets { r.ec(i) | i ∈ ℕ } and H
are closure systems in (O ∖ T, ≤).
(The corresponding closure operators are denoted .re and .he,
respectively.)
Proof:
By
| ||||
(7) |
Every object x has a unique primary object, x.pr,
i.e.
for every x there exists a primary object p,
Proof: Let x be an object. If x is primary then x.pr = x. For an eigenclass x, let i be such that r.ec(i) = x.re. If p.ec(i+1) = x for some eigenclass p then p ≤ r would imply x = p.ec(i+1) ≤ r.ec(i+1) < r.ec(i) = x.re – a contradiction with the definition of x.re. This means that p.ec(j) = x for some j ≤ i + 1 and a primary object p. | ||||
(8) |
The class map .class forms a tree rooted at the instance root
c.
Equivalently, for every object x,
Proof:
Let h be a helix object satisfying |
Corollary: For a structure S = (O, ϵ) the following are equivalent:
An S1ϵ.pr structure is a structure (O.pr, ϵ, ≤) where
| |
The inheritance ≤ is a partial order between objects. | |
| |
The set H.pr of helix classes is subject to the following conditions:
| |
Metaclasses can only have classes as instances. | |
Every object x has a least primary container,
x.class.
(In particular, every object is an instance of a class.) | |
Cycles in ϵ only occur among helix classes,
i.e.
for every object x and every i > 0,
| |
The set C of classes is finite. |
Proposition:
Eigenclass completionFor an S1ϵ.pr structure (O.pr, ϵ, ≤) we define its eigenclass completion as a structure (O, ϵ, .ec, ≤) with the following properties:
Proposition A: (O, ≤) is a partial order. Proof: i.e. for every objects u, v, w,
Proposition B: The .ec map is an order embedding of (O, ≤) into itself. Corollary:
Proof: Follows from the previous proposition and the definition of eigenclass completion. Proposition C: For every objects x, y, there are at most finitely many k such that
Corollary: Every object has finite number of ancestors. Proof: Let x = a.ec(i), y = b.ec(j) for primary objects a, b and let k ≥ 0 be such that a.ec(i) ≤ b.ec(j+k). By condition (ec~B), j+k ≤ i+1, i.e. k is upper bounded by i+1-j. For a non-terminal object x, we denote x.re = r.ec(i) such that x ≤ r.ec(i) and i is maximal with such property. Proposition D: For every non-terminal object x and every i ≥ 0,
Proposition E:
Proof:
Proposition F:
The structure (O, ϵ)
is an S1ϵ structure
satisfying Proof:
We prove the conditions
Class map reductionBy
Proposition:
S1p.pr: The primary structure via the class mapFor completeness, we also provide an alternative axiomatization of the primary structure, based on the .class map.An S1p.pr structure is a structure (O.pr, .class, ≤, r, c) where
Proposition: For a structure S = (O.pr, ϵ, .class, ≤) the following are equivalent:
S1r: Terminal mixins (modules)Motivated by the Ruby object model we introduce a generalization of S1p structures that allows extension of object membership via terminal mixins (modules).An S1r structure is an S1p structure equipped with (Μ, m) where
Note: Transitivity of Μ is not asserted so that Μ is not necessarily a partial order []. The composed inheritance ≤•The composed inheritance, ≤•, is defined as (O, ≤) ○ Μ, i.e. ≤• is a relation between objects such that
The kind-of relation ϵ•The kind-of relation, ϵ•, is defined as ϵ ○ Μ, i.e. ϵ• is a relation between objects such that
Proposition: (ϵ•) = (.ec) ○ (≤•). S1s: Non-terminal mixinsMotivated by the Scala object model we introduce a generalization of S1p structures that allows non-terminal mixins as the third kind of primary objects (in addition to terminals and classes).An S1s structure is a structure (O, .ec, .pr, ≤, r, c, .c) where
Proposition:
ExampleThe following diagram shows an S1s structure that cannot be considered an S1p structure. The eigenclasse has
has 2 parents that are primary objects: A and T .
Therefore,
the set O.pr of primary objects does not form
a closure system.
def p (x:Object) { println (x.toString.replace("Main$$anon$2$", "")) } class A trait T val A = classOf[A] ;p(A) // class A val T = classOf[T] ;p(T) // interface T val a = new A ;p(a) // A@c76887 val b = new A with T ;p(b) // $anon$1@19f9744 val e = b.getClass ;p(e) // class $anon$1 object x extends A ;p(x) // x$@12b644e val y = x.getClass ;p(y) // class x$ assert (A == e.getSuperclass) assert (A == y.getSuperclass) Semi-instance-ofIn the previous example,b.isInstanceOf[T] would evaluate to true .
To reflect this, we introduce semi-instance-of as the
range-restriction of ϵ to semiclasses, i.e.
S1c: Multiple roots and degenerate helixesMotivated by the Objective-C object model we introduce a generalization of S1p structures that allows multiple components of inheritance as well as helixes that have only one class.An S1c structure is a structure (O, .ec, .pr, ≤, .r) where
Proposition:
ExampleThe following diagram shows a component of an S1c structure.
#import <Foundation/Foundation.h> @interface A_: NSObject; @end; @implementation A_; @end @interface B_: A_; @end; @implementation B_; @end int main(int argc, const char *argv[]) { id r = [NSObject class]; id e = object_getClass(r); id A = [A_ class]; id f = object_getClass(A); id B = [B_ class]; id g = object_getClass(B); id b = [B new]; return 0; } S1m: Metaclass redirectionMotivated by the Smalltalk-80 object model we introduce a generalization of S1p structures that allows redirection of the class map on metaclasses (those from the subroot level of the instance tree).An S1m structure is an S1p structure equipped with (ȼ) where
Metaclass .
The following condition is required:
Proposition:
Note:
Condition (1)(iv) means that metaclass redirection (if any) is A sampleThe following diagram shows a sample S1m structure without explicit metaclasses other than c (which is the case of Smalltalk). The dashed arrow from r.ec to ȼ indicates the metaclass redirection which is inherited by all (implicit) metaclasses. Dashed border forb .ec indicates that in Smalltalk,
eigenclasses of terminal objects are fictitious, see
Object actuality.
S1w: Additional twist linksMotivated by another quirk of the Smalltalk-80 object model we introduce a generalization of S1p structures that allows multiple direct descendants of the metaclass root.An S1w structure is a structure (O, .ec, .pr, ≤, r, c) where
Proposition:
ExampleThe following diagram shows an S1w structure that refers to thePseudoContext class as known from Pharo.
Note:
Instantiation of S1ℓ: Non-linear helix and imposed class mapMotivated by CLOS we introduce a generalization of S1p structures that allows non-comparable helix classes as well as redirection of the class map.PreliminariesLet (X, ≤) be a partial order and .f a function on X. We say that an element p ∈ X is an .f-prototype if the following conditions are satisfied:
inheritsthe value of .f from p. Proposition:
DefinitionAn S1ℓ structure is a structure (O, .ec, .pr, ≤, r, c, .¢lass) where
Proposition:
The CLISP built-in core structureThe following diagram shows the built-in core structure of CLOS as implemented by CLISP. The set of displayed classes can be obtained in the following steps:
(∗) Set intersection with C should be applied to exclude eigenclasses.
A sample user structureThe following diagram shows a sample user-created S1ℓ structure in metaclass alignment. Note that
Helix entryThe diagram in the appendix shows that CLISP allows classes with undefined helix entry.S1@: Circular classesMotivated by the Perl object model we introduce a generalization of S1p structures that allows multiple instance roots (while still preserving a single inheritance root).An S1@ structure is a structure (O, .ec, .pr, ≤, r, c) where
Proposition:
Perl circularityBy a Perl S1@ structure we mean an S1@ structure such that the following properties are satisfied:
Proposition:
Assuming just
A sampleThe following diagram shows a Perl S1@ structure together with corresponding Perl code.
S1∗ in particular programming languagesRubyRecall that a Ruby S1 structure [] is a structure of the form (O, .ec, .pr, .sc, r, c) with .sc being the superclass partial function. If we express the forest (O, .sc) as its reflexive transitive closure (O, ≤), we obtain the same list of symbols (and the same signature) as for S1p structures.A Ruby S1p structure is then an S1p structure such that the following properties are satisfied
A Ruby S1r structure is an S1r structure (O, ϵ, Μ, m) such that the following conditions are satisfied:
PythonA Python S1p structure is an S1p structure such that the following properties are satisfied
Proposition: A Python S1 structure [] is an S1p.pr structure with just 2 helix classes. ScalaA Scala S1s structure is an S1s structure such that the following properties are satisfied:
Note: In Scala, mixins (elements of Ϯ) are called traits. JavaA Java S1s structure is a Scala S1s structure with additional properties. In Java, elements of Ϯ are called interfaces (instead of traits).
Notes:
Smalltalk-80A Smalltalk S1m structure is an S1m structure such that the following conditions are satisfied:
A Smalltalk S1w structure can be defined as an S1w structure satisfying the same conditions as above except for the last one. Additionaly, an extra condition might be imposed that subsidiary classes have no instances. A Smalltalk S1r structure is an S1r structure such that the following holds.
Note: The traits facility in Smalltalk [] does not seem to be mature enough to allow serious description.
Objective-CObject membership in Objective-C does not conform to the S1p structure for the following 2 reasons:
CLOSA CLOS S1ℓ structure is an S1ℓ structure such that the following properties are satisfied
PerlThe Perl S1@ structure has been introduced within S1@ structures.Helix classes in comparison
S1ϵ,a: Object actuality and the actualclass mapAn S1ϵ,a structure is a structure (O, ϵ, .a) where
The structure is subject to the following conditions:
For an object x,
we denote x.actuals the (necessarily finite) list of all
non-strict eigenclass successors of x that are actual.
In particular, if x is primary then x.actuals
is the Proposition:
S1s,aObject actuality for S1s structures is subject to an additional condition.
S1c,aFor S1c,a structures,
S1m,aFor S1m,a structures, the following additional condition is required:
Proposition: The imposed actualclass map .aȼlass forms a pseudotree (which can be called the (imposed) actualclass pseudotree). Its pseudoroot consists of elements of ȼ.actuals. The following diagram shows a sample Smalltalk-80 S1m,a structure with its actualclass pseudotree. The pseudoroot contains theMetaclass class and its eigenclass.
Non-actual eigenclasses are not displayed.
Actuality in particular programming languagesThe following table shows support for actual eigenclasses in the considered programming languages. In Python, Java and CLOS, all actual objects are primary. Smalltalk and Objective-C have fixed set of actual eigenclasses consisting of first eigenclasses of classes.
RubyRuby supports dynamic eigenclass actualization. In fact, there are 2 actuality systems in MRI, corresponding to two actualclass maps:
S2r: Linearization of terminal mixinsAn S2r structure is an S1r structure equipped with (≤Μ) where
Proposition:
Inclusion listsFor an object x the (own) inclusion list of x, denoted x.incs, corresponds to (x.incl−1, ≤) without the bottom. More specifically, x.incs is a (possibly empty) list of modules defined by
Proposition: An S2r structure can be expressed as (O, ϵ, .incs, m). In RubyA Ruby S2r structure is an S2r structure such that the S1r-reduct (obtained by forgetting the inclusion order) is a Ruby S1r structure.The structure is also specified in [] where it is referred to as the S2 structure. Since inheritance (O, ≤) in Ruby is a forest, the MRO relation is also a forest, which is the designed characteristics. For a sample structure, see [] or an S2ϵ sample. S2s: Linearization of non-terminal mixinsIn an S1s structure, the Μ relation is obtained implicitly is a subset of the inheritance ≤ defined by (x,y) ∈ Μ iff one of the following conditions is satisfied:
ownmeans that all objects strictly between x and y in inheritance are mixins. An S2s structure is an S1s structure equipped with (≤Μ) where
Proposition A:
Proposition B: In contrast to S2r structures, the following properties are satisfied:
In ScalaLike with Ruby S2r structures, a Scala S2s structure is an S2s structure such that the S1s-reduct is a Scala S1s structure. Since the inheritance on the set Ͼ of classes is a tree, the MRO relation, restricted to Μ' =Notes:
S2p: Linearization of ancestorsThe Μ relation, in its default semantics (which is overridden in S1r or S1s), equals the inheritance ≤, i.e.
Note: The (c3) condition is enforced by the C3 linearization algorithm []. In PythonBy default, Python uses C3 linearization. A request for creation of a class with c3-incompatible parents results in an error. This behavior can be altered by explicitly setting the__mro__
attribute.
Note:
As of version 3.2,
Python allows to set quite arbitrary ancestor lists to In CLOSIn CLOS, the (c3) condition is mandatory – according to Common Lisp HyperSpec [].In PerlBy default, Perl uses depth-first linearization so that even (c2) is not guaranteed. Optionally, theuse mro 'c3' S2ϵ: IclassesThis section provides anϵ-axiomatizationof S2r structures, similarly as S1ϵ structures are S1p structures axiomatized via ϵ. The description introduces iclasses which are objectivizedelements of Μ ∖ O.∆. By an S2ϵ structure we mean a structure (Θ, ϵ, m) where
Sample structureThe following diagrams show a sample S2ϵ structure from Ruby.
Kernel
module together with its inclusion into the Ruby helix.
The structure that corresponds to the merge of both diagrams can be created by the following Ruby code: module M; end module N; include M end class A < BasicObject class << self; include N end end class Object; def ec; singleton_class end end p M .ancestors # [M] p N .ancestors # [N, M] p A .ancestors # [A, BasicObject] p N.ec.ancestors # [Module, Object, Kernel, BasicObject] p A.ec.ancestors # [N, M, Class, Module, Object, Kernel, BasicObject] Notes:
S2ϵ versus S1ϵProposition:
S2ϵ versus S2rWe denote Μ the relation on O defined by
module in the context of its own includer. The bijection .ω in turn induces a partial order ≤Μ on Μ:
Proposition: Let S = (Θ, ϵ, m) be an S2ϵ structure and denote S r = (O, ϵ, ≤Μ, m).
Eigenclasses of iclassesAccording to the definition, for every iclass x, the eigenclass map .ec is
AppendixThe ontological structure of ϵThe document [] provides a generalization of object membership as it applies to ontological structures based on RDF Schema. The generalization structure, denoted S1o, is distinguished by the following features:
PrototypesThe document Object Membership with Prototypes [] shows that it is also possible to refine the instance-of relation the opposite way by eigenclass predecessors of objects, rather than successors. Such implicit objects are called (instance) prototypes. The corresponding S1ȷ structures are introduced as structures (Θ, O, ϵ) such that (Θ, ϵ) is an S1ϵ structure without terminal objects, and O is a subset of Θ such that the substructure (O, ϵ) is an S1ϵ structure whose non-terminal objects form the set Θ.ec.↧. Objects from Θ ∖ O are the instance prototypes. The inclusion Θ.ec.↧ ⊆ O establishes a one-to-one correspondence between the i-th metalevel of (Θ, ϵ) and the (i+1)-th metalevel of (O, ϵ) for each natural i.
It is shown how
S1ȷ structures
apply to the JavaScript programming language.
As a particular conclusion which can be drawn,
JavaScript cannot be declared to be The Python Object ModelThe document [] provides a brief description of Python's S1 and S2 structures.CLOS/CLISP metaobject classesThe following diagram shows inheritance between built-in descendants of themetaobject class in CLOS as implemented by CLISP 2.49.
The set of displayed classes equals mo .↧.↥
(without eigenclasses) where
mo is the metaobject class.
Red oval indicates that for the m class (and its descendants),
the helix entry m .he is undefined.
Correspondence to related former documentsSpecialized description of the instance–inheritance structure of the Ruby object model is provided in []. The structure is then further developed in [] together with a comparison with Smalltalk-80 []. There are slight differences in notation and terminology which are summarized in the following table.
References
Browser compatibilityTo be viewed correctly, this document requires advanced browser features to be supported, including
Document history
LicenseThis work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License. |