The structure arises as a generalization of the innermost core of the object model of the Ruby programming language. In Ruby, the .ec map is total – every object has an eigenclass. The following equalities hold:
As an essential feature, the structure supports circular objects, i.e. objects x such that x ϵ x. This is also the main indicator of applicability. It is shown how the structure applies to class-based programming languages (Ruby, Python, Java, Scala, Smalltalk, Objective-C, CLOS, Perl and Dylan), prototypal languages (JavaScript), and ontology languages (RDF Schema, OWL Full).
A general mathematical structure of object membership is described in an affiliate document []. A gradual set-theoretic representation is provided with the exact correspondence of ϵ, ≤, .ec and derived constituents of the structure to fundamental notions of set theory.
As a result, a uniform and mathematically precise view of an essential part of object technology is provided.
membership. Best readability is achieved when the sequences of symbols from the following two lines look (almost) identically.
OO-terms are included. Basically, we are interested in object models []. The word
modelindicates that something is abstractly represented in a structured way. The word
objectindicates uniformity – there is a uniform unit of representation called object.
This document identifies the following three relations as the core relations of object technology:
r = BasicObject c = Class A = c.new(r) B = c.new(A) s = A.new u = B.new v = B.new
class << s; end class << v; end
Notes: (See Ruby core sample.)
c and r are only immediate in the partial structure,
restricted to chosen objects.
In the complete Ruby built-in structure,
there are 2 objects between c and r.
r to s in the sample structure.
Therefore, what the document essentially contains is an axiomatic description
of families of structures that arise from the three core relations.
Since the relations are fundamental,
their description should contribute to foundations of object technology.
Presumably, the above question can be stated as
classless.)
This document is predominantly concerned with structures satisfying ϵ2 ≠ ∅. That is, x ϵ y ϵ z for some (not necessarily distinct) objects x, y and z. It turns out that in all the introduced structures, the following stronger condition holds:
The concept of type is regarded as something more complex
(an therefore less fundamental) than things described in this document.
We use the term type
exclusively as a mean of quotation (reference)
of particular concepts by other parties
(e.g. types
as particular objects in Dylan,
or abstract power type system
for the abstract structure of Cardelli's power types).
As a consequence, this document becomes virtually disjoint with
the following two books,
both of which claim to provide foundations of object-oriented programing.
(The metaclass
term can be used as an indicator
for the disjointness.
There is no occurrence of this word in either of the books.
Similarly for meta-class
,
cf. [].)
Excerpt from the Preface: [] This book develops a theory of objects as a foundation for object-oriented languages and programming. Our theory provides explanations for object-oriented notions in terms of a few basic primitives, and can be useful for the design and understanding of programming languages.
Excerpt from the publisher's overview: [] This text explores the formal underpinnings of object-oriented languages to help the reader understand the fundamental concepts of these languages and the design decisions behind them.
| Rule name | Short expression | Using variables | Set-theoretic counterpart | RDFS rule(s) |
| Transitivity of ≤ | (≤) ○ (≤) ⊆ (≤) | if x ≤ y ≤ z then x ≤ z | (⊆) ○ (⊆) ⊆ (⊆) | rdfs11 (and rdfs5) |
| Subsumption of ϵ | (ϵ) ○ (≤) ⊆ (ϵ) | if x ϵ y ≤ z then x ϵ z | (∈) ○ (⊆) ⊆ (∈) | rdfs9 |
| Monotonicity of ϵ | (≤) ○ (ϵ) ⊆ (ϵ) | if x ≤ y ϵ z then x ϵ z |
B)}.)
The table also indicates that ⊆ (set inclusion) and ∈ (set membership) are the respective set-theoretic counterparts in of ≤ and ϵ. However, the latter correspondence is indirect – we will further introduce ∊, a restriction of ϵ, to be the direct correspondent of ∈, see Set-theoretic interpretation.
In contrast to subsumption,
the monotonicity rule has no set-theoretic counterpart.
In set theory,
it is not true that
for every sets x, y, z,
if x ⊆ y ∈ z then x ∈ z.
(For example, if x ⊂ y ∈ {y}
then x ∉ {y}.)
Nevertheless,
monotonicity of ϵ is satisfied in the major part of object technology.
The monotonicity
term comes from the following equivalent formulation:
for every objects x, y,
⋮ The Coreis provided by the family of basic structures. The diagram on the right shows the signature of these structures. In addition to the ϵ, ≤ and .ec relations mentioned in the introduction there are additional constituents:
powerclassis interchangeable with
eigenclass.
essential mathematical modelfor the core structure of object technology. This is for the following reasons:
Note:(⁎) This case relates to prototype-based programming languages and is more carefully handled in []. An alternative interpretation is proposed, in which ϵ is equal to ≤.
We do not consider all prototype-based programming languages to have a purely prototypal core structure. In particular, in JavaScript [], ϵ ≠ ∅. We base this judgement on the following observations:
x instanceof y can evaluate to true
for some x and y.
Note that we did not mention the word object
anywhere in the definition.
This is because we have disobeyed the two-sortedness
–
we unified the sorts
T and C into one set O.
In the two-sorted view of ϵ the term object
is exclusively
reserved for elements of T.
This is expressed by:
reificationcan be overridden by
identity. This approach seems to be supported in particular by the Java programming language. In Java, the names of introspection methods like
getClass() or
getSuperclass()
suggest that it is a class what is returned, rather than its reification.
In the book Java reflection in action
[], both
agreement and disagreement to the uniformity principle can be observed.
(According to page 23, classes are objects. According to page 268, there is a
distinction between class and class object.)
This is the main document that provides an introduction to the subject as well as synthesis of other documents.
The document describes the ultimate mathematical model of The Core
and its connection to set theory.
In particular, it is shown that object membership, ϵ,
arises by the following fundamental equality:
boundedpart, a well-founded relation, and ϵ is the
monotonicpart. The main correspondence between (the core structure of) object technology and set theory can be then expressed as
The assumption of monotonicity ((ϵ) = (ϵ)) and of totality of .ec results in the family monotonic eigenclass structures. This family has a simple description (simpler than the general case of basic structures) which is provided in the referred document. The restrictions can be considered acceptable:
Historically, this document introduced the term object membership (together with the ϵ symbol) and originally was the main document. The (canonical) core structure of OOP arises by unifying core structures of Ruby and Python. It can be viewed as either the Ruby core structure with multiple inheritance and user-created explicit metaclasses allowed, or the Python core structure equipped with eigenclasses.
The core structures of Java, Scala, Smalltalk, Objective-C, CLOS or Perl are viewed as modifications of the canonical structure. (See also Specializations of ϵ.) Additionally, refinement structures are described which provide linearization of object's ancestors.
The document provides a generalization of object membership as it applies to ontological structures based on RDF Schema. In contrast to object-oriented programming the following features are present:
sortof objects, called properties. Like terminals, properties are not descendants of the inheritance root. Unlike terminals, properties can have descendants.
As already observed
on the example of the JavaScript programming language,
prototype-based languages cannot be, in general,
declared to be classless
or to be devoid of the instance-of relation
(despite the traditional view []).
Moreover, it can be observed
that in the JavaScript core structure
(O, ϵ, ≤, r, .ec),
not only ϵ but also the .ec constituent is non-empty.
The following correspondence holds:
x == y.prototype.
The document provides an explanation of the notion of a powertype in terms
of the core structure.
In particular, it is shown that, in a suitable axiomatic restriction,
the Cardelli's Power() operator coincides with .ec.
That is, Cardelli's power types are powerclasses in the abstract setting.
The only difference is that Power(x) is only defined
for Classes
(called types
).
Subsequently, the adoption of powertypes in metamodelling is considered, as well as powertype relationship in RDF Schema.
Historically, the Smalltalk programming language is of fundamental importance to the core structure of object technology:
The document provides a more elaborate alternative to the present document.
The title question is used as a linguistic device for the exploration
of the object model core in various contexts.
There are about 20 investigated environments.
The metaclass term is used as a label for an approach to
OOP foundations.
The metaclass approach
is based on four rules in the spirit of Occam's razor:
(1) dispense with types,
(2) dispense with calculus,
(3) support object identity,
(4) assume metaclass pre-condition (classes are objects
).
Featherweight Java is the most popular formalization of the most popular object-oriented programming language. In the referenced document, the formalization is adjusted to provide a clear definition of the core structure of the underlying data model.
The document provides a detailed description of the Ruby Object Model
(as of version 1.9)
via abstraction refinement.
The object model is incrementally specified in the series of abstract structures
together with their possible transitions.
The most abstract, initial structure, denoted S0,
just introduces the basic nomenclature of objects:
terminals, classes and eigenclasses.
The next structure, S1, is the
core structure of Ruby
in the sense introduced at the beginning of this document.
The structure is (exactly what is) induced by
superclass and eigenclass links between objects.
The yet subsequent structure, S2, equips S1
with module inclusion lists
so that the complete inheritance structure is established
(referred to by MRO,
which stands for method resolution order).
There is an in-between structure,
denoted S1r in
[],
which encompasses just the extension of the Ruby's (canonical) object membership,
ϵ,
to the full
membership, ϵ•,
which can be introspected by the is_a? built-in method
(see also Specializations of ϵ).
There are more than 20 structures in the gradual description. The resulting structure (still providing just an abstraction of the Ruby object model, though far more detailed than S1) can be viewed as a naming multidigraph, consisting of nodes and uniquely labelled arrows between them.
The document provides a set-theoretic representation of the core structure of Ruby (again referred to as the S1 structure) using the bottom stratum map .ϱ between objects in an (ω+1)-superstructure (V, ∈). In contrast to the embedding presented in [], the embedding from [] maps all objects to elements of finite stages. As a result, for objects x, y whose metalevel index is lower than a predefined number k,
The document focuses on the description of the S1 structure using the material from the previous two documents. In all these three documents, object membership is expressed in the composition (.ec) ○ (≤), the ϵ symbol is missing. Moreover, ≤ is considered to be defined only between non-terminal objects.
Historically, this document is the first description (available at atalon.cz) of the Smalltalk-80 correspondent of the Ruby's S1 structure. The document can be regarded as a precursor to the dedicated section.
essential structure of ϵ.
The Wikipedia page en.wikipedia.org/wiki/Eigenclass_model containing the article has been created in October 2012 by the author of this document. Several major edits followed until January 2013. In October 2013, the page has been deleted (changed to a redirect to Ruby (programming language)#Semantics) by Wikipedia administrators on the following grounds:
other that
other than
and instances of each other.
Class class in mainstream programming
Java
Notes:
Let us write x ϵ y for
the object x is an instance of the class y
.
By using the ϵ symbol (lunate epsilon) for the instance-of relation
we suggest the correspondence:
There is a second point that should be noted in the expression x ϵ y: both the object x and the class y are denoted by a lowercase letter. This suggests that we are focused on programming languages that support the following uniformity principle of ϵ:
metaclassin publications about a particular programming language is a good indicator that the language supports handling of classes as objects.
ordinaryobjects. The instance-of relation is displayed by dark blue arrows: x ϵ y iff there is a blue arrow from x to y.
For an object x we denote x.϶ the set
of all instances of x and call it the extension of x.
Ordinary objects have empty extension.
The sample structure is saturated
in the sense that classes are distinguishable
by their instances: different classes have different extensions.
This allows to derive a partial order,
denoted ≤, and called inheritance,
between the 7 objects by:
o.϶ = {s, u, v, A, B, o, c}
c.϶ = {A, B, o, c}
A.϶ = {s, u, v}
B.϶ = {u, v}
○is interpreted left-to-right. The equality can be read as: x is an instance of y iff the class of x is an inheritance descendant of y.
Observe that classes o and c are circular –
they are instances of itself.
Moreover, every object is an instance of o
and classes are exactly the instances of c.
o and c are distinguished built-in
classes, usually named Object and Class, respectively.
The remaining part of the structure is built incrementally,
by adding userclasses
A and B and their instances
s, u and v, one by one.
Each of the addition of these five user objects
x can be formally expressed as class instantiation:
x = q.new(p1, …, pn)
x = q.new()
which we further abbreviate to x = q.new.
Since the sample structure only has single inheritance,
new class creation can be expressed by
x = c.new(p) with the single requested parent p.
As a result, the structure is built by the following five assignments:
A = c.new(o);
B = c.new(A);
s = A.new;
u = B.new;
v = B.new
; used as a delimiter between the assignments),
if preceded by o = Object and c = Class,
is a valid line of code in the Ruby programming language
for the creation of the sample structure.
o,c},
O1 = O0 ∪ {A},
…,
O5 = O4 ∪ {v} = Ō
so that O0 is the set of built-in objects of the sample structure
and for each i = 1, …, 5,
the set Oi corresponds to
an addition of a single object into the structure.
Note that most of the intermediate structures (Oi, ϵ)
do not satisfy the extensionality principle that allowed us
to distinguish classes as objects with non-empty extension
and to derive inheritance via inclusion of class extensions.
To capture also the intermediate structures,
the inheritance relation has to be prescribed explicitly.
Therefore, we extend the signature from
(Ō, ϵ) to
(Ō, ϵ, ≤).
We call this instance-inheritance
structure the primary structure of ϵ.
Note that since (ϵ) = (.class) ○ (≤) we can use the signature (Ō, .class, ≤) as well.
Where applicable, a diagram is provided showing how the sample structure is obtained as a restriction of a finer structure.
new method.
The instance-of relation between the 7 objects can be detected via
the is_a? method (aliased as kind_of?).
In the restriction to classes, the <= method corresponds to ≤.
The .class map is provided by the class introspection method.
o = Object c = Class A = c.new # class A; end B = c.new(A) # class B < A; end s = A.new u = B.new; v = B.new
o = object
c = type
A = c('A', (), dict()) # class A(): pass
B = c('B', (A,), dict()) # class B(A): pass
s = A()
u = B(); v = B()
callingclasses. Also the classes
A and B can be created this way,
though not so transparently as in Ruby.
The instance-of relation between x and y is detected
by isinstance(x,y).
Inheritance between classes x, y is detected by:
x < y iff issubclass(x,y).
For every object x,
the expression type(x) returns the class of x.
classlessand thus devoid of the instance-of relation. However, as we have already mentioned before, we do not consider this characteristics to be applicable to JavaScript. The diagram below demonstrates that JavaScript allows for the creation of our sample structure. (So that all of
o, c, A and B
are examples of JavaScript classes.)
Every (user) object can be created via the new operator.
The instance-of relation between the 7 objects can be detected via the
instanceof operator.
The .class map is provided by the constructor property.
Inheritance between classes can be detected via the isPrototypeOf method
as follows:
y.prototype.isPrototypeOf(x.prototype).
Note:
To simplify the code, inheritance between B and A
is achieved using the non-standard property __proto__.
o = Object; c = Function A = new c B = new c; B.prototype.__proto__ = A.prototype s = new A u = new B; v = new B
subclass: method.
The instance-of relation between the 7 objects
corresponds to the isKindOf: introspection method.
The introspection method named class only partially corresponds to
the .class map: while it agrees on ordinary objects, it disagrees on classes.
o := Object. c := Class. o subclass: #A. A subclass: #B. s := A new. u := B new. v := B new.
class A {}
class B extends A {}
class Xx {
public static void main (String[] xx) {
Object
o = Object.class,
c = Class.class,
A = A.class,
B = B.class,
s = new A(),
u = new B(), v = new B();
}
}
In the Java programming language, classes can be regarded as objects
due to the reification facility.
For a class named A, the class objectof
A
is referred to by A.class.
Note that in contrast to Ruby,
A.class does not refer to the class of the class named A.
As a consequence, there is a notational duality between (non-reified) classes
and their object counterparts.
The instance-of relation between objects x and y
where y is known to be a reified class named Y
can be detected either via
x instanceof Y, or
y.isInstance(x).
x.getClass().
If x is a (reified) class other than o,
then x.getSuperclass() is
the (reified) inheritance parent of x.
Note that the method names
suggest that it is a class what is returned, rather than a class object.
var o = classOf[Object] var c = classOf[Class[_]] class A class B extends A var s = new A var u = new B; var v = new BScala adopts the Java's concept of reification of classes. For a class named
A,
the expression classOf[A] refers to the class object. Note again that
classOf[A] is not the class of A.
Introspection facilities for the instance-of relation and inheritance between
classes are similar to those of Java.
let o = <object>; let c = <class>; let A = make(c); let B = make(c, superclasses: list(A)); let s = make(A); let u = make(B); let v = make(B);The Dylan programming language fully supports the
classes are objectsprinciple []. Every user object can be created via the
make method.
Inheritance between classes is detected via subtype?,
the instance-of relation between objects and classes is detected via
instance?.
Finally, the object-class method is the exact correspondent to the
.class map.
classes are objectsprinciple. (However, there is still some sort of notational distinction for classes.) The instance-of and inheritance relations between objects can be detected via the built-in
typep and subtypep methods, respectively.
(defvar o (find-class 'standard-object))
(defvar c (find-class 'standard-class))
(defvar A (make-instance c :name 'A))
(defvar B (make-instance c :name 'B :direct-superclasses (list A)))
(defvar s (make-instance A))
(defvar u (make-instance B)) (defvar v (make-instance B))
Gray color in the code indicates that
we consider two possible interpretations of
c,
shown in the diagrams below.
In the (a) case,
the class map between the 7 objects is provided by the class-of method.
c corresponds to standard-classc corresponds to classexampleprefix
ex: is used for the user-created objects.
ex:B rdfs:subClassOf ex:A . ex:s rdf:type ex:A . ex:u rdf:type ex:B . ex:v rdf:type ex:B .The sample built-in classes
o and c are those
named rdfs:Resource and rdfs:Class, respectively.
The rdf:type property stands for the instance-of relation, ϵ.
Inheritance between classes is expressed via the rdfs:subClassOf property.
o and c classes are coincident,
so that the sample structure contains one object less.
The diagram also indicates that there is a non-degenerateinterpretation, with
c set to the gray object labelled by
c.
In this document, we prefer the first interpretation,
since we do not consider the gray object to be a class.
@interface A: NSObject; @end
@interface B: A; @end
@implementation A; @end
@implementation B; @end
int
main(int argc, const char *argv[]) {
id
o = [NSObject class],
s = [A new],
u = [B new], v = [B new];
return 0;
}
isKindOfClass: method.
The class_getSuperclass method can be used for the introspection of
inheritance between classes.
Similarly to Smalltalk-80, the class introspection method only agrees with
the .class map on ordinary objects.
For a class x, the expression [x class] evaluates to x.
(This is in contrast to Smalltalk-80,
where x class is always different from x.)
isa introspection method.
The semantics of ϵ is then adhered to by method lookup.
[]
The diagram below shows the sample structure in the correspondent modification.
package UNIVERSAL { sub new { bless {}, $_[0] } }
package A { }
package B { our @ISA = A }
my
$o = UNIVERSAL,
$s = A->new,
$u = B->new, $v = B->new;
c.)
As a consequence,
every class is the most specific descriptor for its direct instances.
Equivalently,
objects instantiated by the same class have the same description.
In particular,
every class has the same set {c, o} of describingclasses in (Ō, ϵ, ≤).
instance-ofterm for ϵ. Instead, we call the ϵ relation object membership. If x ϵ y then x is said to be a member of y. We can also say that y is a container of x.
Proposition: For every x, y from Ō,
classmap
Observations:
object construct can be used to create
ordinary objects that have its own meta-object.
isa pointers,
green links to super_class pointers.
[]
id e = object_getClass(o), f = object_getClass(A), g = object_getClass(B);
e, f and g are created
together with classes o
(the built-in NSObject class), A and B, respectively.
object
construct for s and v instead
of the new operator used in the
primary sample.
object s with A val u = new B object v with B val e = s.getClass val g = v.getClass
Full uniformity of the structure provides the following simplifications:
Object and Class.
r = BasicObject c = Class class A; end class B < A; end u = B.new v = B.new
0, 1, 2, ….
The structure is built using two sorts of links.
Green links correspond to the superclass introspection method.
A green line going from an object x upwards to an object y indicates
that y is an (the) inheritance parent of x.
For curved lines (those starting at the top of metalevel 2 and higher)
the upward direction is
expressed explicitly by an arrow.
All the other superclass links are drawn as a Hasse diagram.
Gray arrows (directed left-to-right) show the infinite regress of meta-objects.
Each object x has its own meta-object,
called the eigenclass of x,
which is one metalevel higher than x.
The prefix eigen stands for own
– different objects have different eigenclass.
In the Ruby comunity, the term eigenclass
appeared around the year 2005.
Previously, the term singleton class
has been used.
As a (historical) consequence, the corresponding introspection method is named
singleton_class.
We use the notation x.ec for the eigenclass of x,
so that x.ec corresponds to x.singleton_class.
The .ec map is then the eigenclass map shown by gray arrows.
Furthermore, let x.ec(i) be the i-th application of .ec
to x.
Components of the .ec map are eigenclass chains
of the form x, x.ec, x.ec(2), x.ec(3),
….
The inverse of .ec is denoted .ce.
For x from O.ec,
x.ce is the eigenclass predecessor of x.
Let .ec∗ be the reflexive transitive closure of
.ec.
For an object y, let y.pr be the primary object
of y, that is, the first object of the eigenclass chain
y.pr.ec∗ to which
y belongs.
The notation is adapted to multiple inheritance. If single inheritance is asserted, we can use the .sc notation for ≺ so that x.sc = y iff x ≺ y. For an object x, the object x.sc, if defined, is the superclass of x. The core structure of Ruby can be then expressed as (O, .ec, .sc). []
is_a? introspection method.
The method is aliased as kind_of?.
(There is also the Class#=== introspection method,
which detects the inverse relation, ϶.)
If x is a member of an object named B
then one can say that x is-a B.
The set B.϶ of all members of B
can be referred to as Bs.
This convention can be used for nomenclature of objects.
Moreover,
there can be a distinction between the names that are built using this convention
(these names are capitalized and styled)
and those names that are not.
In Ruby,
the built-in classes Object, Module and Class
provide such a distinction.
Objects are objects that are not blank slateobjects.
Modules are modules together with Classes.
Classes are classes together with eigenclasses.
is-acorresponds to inheritance. The reasoning goes as follows. If
A and B are classes
such that A ≤ B (A is a subclass of B)
then one can say that
A is a B,
A is also an instance of B.
The sentence structure can be expressed as
an-A is a-B(two pairs of article-noun and a verb between). However, the longest characteristic subsequence is
is awhich leads to another hyphenation and to saying that
A and B.
(so that theAis-aB
A's article is dropped and the B's article is
secluded from B),
meaning that the (A,B) pair belongs to the is-a relation.
This abbreviated statement then becomes ambiguous since one way to interpret it is
A is a B (削除ここまで)Note:
The two different meanings of is-a
have been analyzed by R. Brachman
[]
[].
Socrates is a man.
a cat is a mammal.
is-acan be resolved according to the adherence to the uniformity principle stated in the introduction. If classes are not considered to be objects (individuals) then
is-ais resolved in favor of ≤. Otherwise, if classes are among objects (as is our assumption) it is reasonable to interpret
is-aas ϵ. At present, this second interpretation is supported only rarely. The Ruby introspection method
is_a? and the Objective-C isa pointers
are two notable examples.
Others can be found in publications about Smalltalk
[]
or Self
[].
Another example is the book by Forman and Danforth
[]
which uses isA for ϵ.
A more detailed discussion can be found in
[].
Classes
= c.϶ = O.ϵ.↧
Class.
It is the unique inheritance parent of r.ec.
ordinary objectsfor elements of T. The new terminology is similar to that introduced in the ObjVlisp model [] [] [] where the term
terminal instancesis used. Note that for an object x the following are equivalent:
Class
(i.e. x is a member of the c object which is named Class).
Classes.
The terminology for the set H = r.ϵ∗ is based on the similarity of the diagrammatization of (H, ≤) with a right-infinite helical curve.
Classes.
I.e. it is a set of distinguished non-terminal objects such that
every non-terminal x has a least ancestor from Y.
Equivalently, Y is such that
every object x has a least container from Y.
If .y is the corresponding closure operator
(that maps a non-terminal object to its least ancestor from Y),
then the corresponding classification map
(that maps any object to its least container from Y),
equals .ec.y.
Observe that since both .ec and .y are monotone,
any classification map is monotone, i.e. for every objects a, b,
Note that the sets C, R and H
are all classification systems.
(In fact, since in Ruby the inheritance on Classes forms a tree,
any subset of O ∖ T containing r
is a classification system.)
We denote the corresponding closure operators by
.c, .re and .he, respectively.
In the case of .c, we extend the definition to all objects: we let .c to be the closure operator corresponding to the closure system C ⊎ T in (O, ≤). This allows us to conveniently express the set of all primary objects as O.c.
Further observations:
Classes forms a
trivial classification system,
with .ec the corresponding classification map.
However, the eigenclass map is not useful for classifying objects since
different objects have different eigenclass,
so that each object is classified as different from every other object.
The most important classification system
is the set C of primary non-terminal objects.
Objects from C are called classes.
The corresponding classification map is denoted .class.
(So that .class = .ec.c.)
For an object x,
the object x.class is said to be the class of x.
Note that the just introduced meaning of class
and class-of
possesses the following fundamental consistency:
Classes.
Classes are classes together with eigenclasses.
In Ruby, all classes reside in the metalevel 1.
As a consequence, .class.class maps constantly to c.
The Ruby introspection method named class is in 100% correspondence
with the .class map.
instanceas such does not distinguish any objects. Every object is an instance of some class. In particular, every object is an instance of the inheritance root r and every object is a direct instance of its class.
By allowing indirect instances
our terminology follows the semantics of
the isinstance() method of Python
or the instanceof operator from Java.
In Ruby, the introspection method instance_of?
corresponds to direct-instance-of.
(However, the Ruby Specification []
allows indirect instances.)
Note that
y is the eigenclass of x then
x.instance_of?(y)
always evaluates to false.
metaclass:
Observations:
w = Module.new so that the Module class
(which is the parent of c) has a terminal member w.
Then
Classes
that do not have terminal members.
Metaclass
we could express the set c.↧ (= c.ec.϶)
as Metaclasses.
This suggests to define metaclasses as the primary Metaclasses
just like classes are primary Classes.
However, this would require an additional term for non-primary Metaclasses.
Moreover, the explicit/
implicitadjectives seem to be an established convention. [] [] []
We denote .a the corresponding closure operator and let .aclass = .ec.a be the classification map. For an object x, x.aclass is the actualclass of x – the least ancestor of x.ec that is actual. The set O.a of all actual objects is the actuality extent. We can view the (O, ϵ, .a) structure as an implementation-oriented refinement of (O, ϵ). In particular, x.aclass can be regarded as the actual startpoint of method lookup for x – non-actual eigenclasses between x.ec and x.aclass are skipped.
The diagram below shows
the actuality extent of allocated objects
for the sample structure.
The extent arises
after opening the eigenclasses of A and v.
The actualclass map (in the restriction to actual objects) is shown by blue arrows.
Note that the map forms a tree rooted at c.ec(2).
r = BasicObject c = Class class A; end class B < A; end u = B.new v = B.new
class << A; end class << v; end
A.ec(2) and B.ec
have been allocated but not opened.
This is an implementation feature of Ruby.
Every newly created class x has its eigenclass allocated.
When the eigenclass x.ec(i) is evaluated
(e.g. by class << x; end for i = 1)
then
MRI/YARV
makes sure
that x.ec(i+1) is allocated.
As a consequence,
we can distinguish 2 actuality extents:
one for actually referenced (evaluated) objects
and a larger one for allocated objects.
As already mentioned, the diagram shows the structure for the larger extent.
Objects that have been allocated but not referenced are shown
in light blue.
The actualclass map shown by blue links could be denoted .klass,
since it is maintained by the implementation
via the klass field in the C source.
Note that there cannot be an introspection method for .klass
due to the probe effect.
There could only be an introspection method
for the actualclass map for the smaller extent,
but even this is not supported since
it is considered to be an implementation property.
The reason for having an extra object allocated in each eigenclass chain of classes is an efficient update of the actualclass map for inheritance descendants. This does not affect terminal objects (or their eigenclasses). Since they cannot have descendants, they do not need to have their eigenclass allocated.
classes are objectspattern.
Unfortunately, the Smalltalk-80 core structure possesses uniformity deficiencies which were compensated by equivocal terminology in the Smalltalk's literature. []
To describe the Smalltalk-80 counterpart of the Ruby core structure we use a specially restrained terminology in which the following terms are (at first) avoided:
x class evaluates to y
we do not say that y is the class of x.
superclass introspection method.
There is a single line for which the upward direction is
expressed explicitly by an arrow.
All the other superclass links are drawn as a Hasse diagram.
The blue links correspond to the class introspection method.
A blue line starting at x and ending in y
(with an arrow head pointing to y)
indicates that
the expression x class evaluates to y.
r := ProtoObject. c := Class. mc := Metaclass. Object subclass: #A. A subclass: #B. u := B new. v := B new.
r, c and mc) and
subsequently the user-part of the structure is created.
The built-in part forms a substructure
—
it contains exactly the objects reachable from the mc object
via a combination of blue and green links.
(Note that the substructure is generated by any single object it contains,
not just mc.)
Moreover, it is a minimum (nonempty) substructure,
since the mc object is reachable from any object
(via at most 3 blue links).
mc object.
The straight left-to-right links precede the curved links.
Each curved link is preceded by exactly one straight link.
The remaining, broken-line links precede the straight links,
but without a one-to-one correspondence.
The division of blue links induces a division of objects into 3 metalevels.
x such that
x class == mc.
x such that
x class class == mc.
x from the metalevel 0,
x class class class == mc.
u and v).
mc
from metalevel 1.
Further observations:
r is the top of the metalevel 1 as well as of the union
of metalevels 1 and 2, w.r.t. inheritance.
r class is the top of the metalevel 2, w.r.t. inheritance.
r class is the object c from metalevel 1.
(x class) ≤ (y class).
x is an object from metalevel 1 different from r,
then
x class superclass == x superclass class.
x := r class and y := c,
then x ≤ y (we even have x superclass == y)
but x class equals mc
which is not an inheritance descendant of y class.
class,
class-of,
metaclassand
instance-ofby applying Ruby-based terminology and notation to Smalltalk. Let
The differences between the core samples can be listed as follows:
mc class (named Metaclass) constitutes a structural
change as a receiverof blue arrows.
redirectedto
mc.
mc otherwise
(i.e. if x is an implicit metaclass).
isKindOf: introspection method.
The imposed instance-of relation
is the range restriction of imposed membership to classes,
so that it equals the composition (.ȼlass) ○ (≤).
By using imposed membership for the is-a naming convention,
classes can be expressed as Classes and
implicit metaclasses as Metaclasses.
Moreover,
C.ȼlass.↧
can be considered to be the set of all metaclasses.
The classes Class and Metaclass are
then the only explicit metaclasses.
Notes:
class introspection method in Smalltalk-80
does not correspond to the synonymous method of Ruby.
class introspection method corresponds to the class map,
.class.
class method corresponds to the imposed actualclass map,
.aȼlass.
As a consequence, x class is not necessarily a class.
| For x from | Smalltalk-80 x class evaluates to |
Ruby x.class evaluates to |
| T (terminals) | the class of x | |
| C (classes) | the eigenclass of x | the class of x which is constantly Class |
| C.ec (implicit metaclasses) | the imposed class of x which is constantly Metaclass |
|
Metaclass.
built-inc class.
(.__class__, .__mro__)
__class__ and __mro__ are (built-in) attributes of
Python objects.
The __mro__ attribute is only applicable to classes.
It stands for method resolution order
and stores the list of inheritance ancestors in the order in which they are looked
up during method resolution.
The inheritance relation, ≤, between classes is obtained by
__mro__
__mro__ list is disregarded.
We assume that a potential explicit manipulation of the attribute
is a permutation (changing just the order of classes in the list).
Note:
In addition to the __mro__ attribute,
Python classes also contain another inheritance related attribute:
the __bases__ list.
Apart from the order within the list, the intended semantics of
.__bases__ is that of the .parents map.
However, the correspondence is not asserted.
In particular, the __mro__ and __bases__ attributes are not
kept in sync if they are explicitly manipulated.
We therefore think of .parents to be derived from .__mro__
(satisfying the assumption above) rather than from .__bases__.
The structure is then subject to the following conditions:
Observations:
built-insubstructure containing no objects that are minimal w.r.t. (≺) ∪ (.class).
s is not a class
B.class ≰ A.class
M is a metaclass
class A(): def __new__(a): pass s = A() # TypeError: class B(s): pass
class M(type): pass class N(type): pass class A(metaclass=M): pass # metaclass conflict class B(A,metaclass=N): pass
class M(type): pass class X: pass s = X() # TypeError: s.__class__ = M
defaultaxiomatization of canonical primary structures. In the description, a preparation is already made for the extension by implicit objects. The set of objects in a primary structure is denoted O.pr. This expression can be later resolved to an application of .pr to the extended set O of objects. Similarly, some sentences contain the adjective
primaryto be also applicable in the context of the extended structure.
By a canonical primary structure of ϵ we mean a structure (O.pr, ϵ, ≤, r) where
Notes and observations:
Proposition: Axiomatizations (py~1)–(py~7) and (p~1)–(p~8) are equivalent.
tightin the sense that every class has at most one eigenclass ancestor (necessarily r.ec). This seems to be the simplest way of eigenclass completion. However, since it also disallows classes on metalevels higher than 2, the interpretation of (B) defines a
slightlylarger family than that of (A). Moreover, some axioms for (B) are singled out for further generalization of object membership.
Observations:
Notes:
__attached__ instance variable.
eigenclass. An eigenclass chain is a metaobject tower. As the term suggests, the regression is diagrammatized vertically. The code expressions
[meta x] and
[den x] correspond to
x.ec and x.ce, respectively.
•have a direct counterpart in the axiomatization of the primary structure.
Notes and observations:
free instantiationof any class.
universal object: O = r.϶. Since r is asserted to be a class by e~(1)(2)(4)(5), every object is an instance of r.
Notes and observations:
Proposition:
The diagrams below show the correspondence between a canonical eigenclass structure,
its restriction to primary objects and
the subsequent tight
eigenclass completion.
Note that the tree structure of ≤ is not preserved.
tight
essential mathematical modelfor the core structure of object technology. This is for the following reasons:
actualitystate of eigenclasses.
←does not hold in general.)
| Special | General | |
| .ec is total | Canonical eigenclass structure | Monotonic eigenclass structure |
| .ec is empty | Canonical primary structure | Monotonic primary structure |
Note: For simplification, we introduce slight discrepancy with the more precise document []. The family of structures defined in the following subsection should be more correctly called membership-based monotonic structures since they rely on the prescription
polarsense for relations between sets of objects, so that e.g X < Y means that every object of X is less than every object of Y. Let T = O ∖ O.ϵ.↧ be the set of terminal objects and H = r.ϵ∗ the set of helix objects where ϵ∗ is the transitive closure of (≤) ∪ (ϵ). For a natural i> 0, let ϵi be the i-th composition of ϵ with itself and let ϵ0 be equal to ≤.
Observation: For a structure S = (O, ϵ, ≤, r) the following are equivalent:
⋮ ⋮⋮ wildcardsuperscript from ϵ⁽*⁾ in the signature. Before stating the axioms some preliminary definitions need to be introduced.
Observations:
The following diagram shows an ad-hoc completion (⁎) making each object of the original structure ϵ-grounded. Added objects are displayed in khaki color. See [] for the precise definition.
Notes and observations:
completionis not quite adequate.
defaultvalue of ϖ is the first infinite ordinal so that the rank of an object is either finite of equal to ω. In this case, .d can be defined by
Note that axioms (b~1) and (b~11) can be stated as a single condition (ϵ) = (∊) ∪ (ϵ). This establishes an inclusion lattice between ϵ, ∊, ϵ and ∊ according to the above diagram on the right.
The following table shows similarities and differences between .ec and .ɛϲ.
| y is the powerclass of x,
x.ec = y |
y is the singleton of x,
x.ɛϲ = y |
|
| Members of y | x.↧ = y.϶ | {x} = y.϶ |
| Ancestors of y | x.ϵ = y.↥ | x.ϵ = y.↥ |
| Metalevel index increment (y.mli - x.mli) | 1 | 1 |
| Rank increment (y.d - x.d) on O.∍ | 1 | 1 |
| x (or y) can be unbounded | YES | NO |
⋮non-expanded) basic structures assert that (ϵ-1) ∩ (϶) is a partial map. Moreover, the inverses of .ec and .ɛϲ are distinguished submaps. The presumed axiomatization of .ⱷ is shown below together with the similar axiom (b~8).
For convenience, we let the term α-superstructure mean a superstructure (V, ∊) whose ∊-rank equals α. The axiomatization of complete structures via ∊ can be then expressed as follows:
x being an inheritance root: x is such that x.∍ = V.∍.
| (Let ϖ be a limit ordinal and α an arbitrary ordinal.) | ZFC | MK | Degenerate cases | ||
| V = Vϖ | V = Vϖ+1 | V = Vα+2 | V = V1 | V = V0 | |
| Rank of V | ϖ | ϖ + 1 | α + 2 | 1 | 0 |
| Bounded objects V.∍ | V | Vϖ | Vα+1 | ∅ | ∅ |
| Existence of the (an) inheritance root r (r.∍ = V.∍) | NO | YES | YES | NO, unless V = {r} |
NO |
| Powerclass map .ec is total | YES | YES | NO | YES | |
| Singleton map .ɛϲ is total | YES | NO | NO | NO | YES |
| Boundedness preserved by .ec / .ɛϲ | YES | YES | NO | YES | YES |
Note: In [], the singleton map .ɛϲ is total – unbounded objects have their singleton constantly set to r (considering (V, ∊) as a model of MK).
Note: If R denotes a relation both in S0 and V then .ν is an embedding w.r.t. R if the following equivalence holds for every objects x, y from O0:
Note: (⁎) A simplified description is provided here, see [] for the detailed description.
eigenclassis used for
powerclass.)
In general, for a basic structure S0 = (O0, ϵ▫, ϵ▫⁽*⁾, …), its powerclass completion S = (O, ϵ, ϵ⁽*⁾, r, .ec, .ɛɕ) is created in the following steps:
In a particular programming language, object membership appears in a specialized form.
Such a specialization
can be obtained by adjustments to
the canonical structure of ϵ.
In most cases (5 of 8), it is necessary to refine the structure by additional
constituents so that the minimum signature (O, ϵ)
needs to be extended.
Class < Module
< Object < BasicObject = r.
superclass and singleton_class
introspection methods, respectively.
However,
this is only the (canonical) reduct of what is understood by object membership
in Ruby.
The full
membership, ϵ•,
results from a finer structure which takes module inclusion into account.
Modules are terminal instances of the Module class,
i.e. modules are Modules that are not Classes.
The additional structure is given by the own-includer-of
relation between Modules (classes, eigenclasses, modules) and modules.
If Μ denotes the reflexive closure
(i.e. Μ is self-or-own-includer-of)
then the ϵ• relation is given by
is_a? introspection method
(aliased by kind_of? and, in the inverse, also by Class#===).
You can check that previously we stated the is_a?↔ϵ
correspondence just for the provided sample structures.
Similarly, the canonicalinheritance, ≤, is extended to ≤• by
Modules,
corresponds to the <= introspection method.
This extended inheritance is a multiple inheritance.
In addition, since Ruby supports dynamic module inclusion, ≤•
can have anomalies (as to transitivity and/or antisymmetry),
the problem known as the double/dynamic inclusion problem.
[]
__mro__ attribute of classes,
Python core structures are exactly the primary structures
(O.pr, ϵ, ≤) with two helix classes.
(Therefore, the Python object model conforms to the tight canonical structure.)
Helix classes are named as follows:
type < object = r
classesis used just for a subset of the set C of primary descendants of r. The subset forms a closure system in (r.↧, ≤), so that it can be expressed as C.c where .c is an explicit closure operator added to the canonical structure. The generalized structure is then of the form (O, ϵ, .c). This way the set C is split into classes and non-terminal mixins. In Scala, mixins are called traits, in Java they are interfaces. Mixins are not allowed to be metaclasses.
The structure is then subject to additional constraints. There are no explicit metaclasses other than c, and, more importantly, a single inheritance between classes applies (but not between traits / interfaces). The helix contains 3 classes:
Class < Object < Any = r.
For Java, the Any
class can be thought of as a fictitious root allowing primitive values to be objects
– they become objects that are not Objects.
Mixins (traits / interfaces) are among descendants of the Object class.
Java in addition disallows interleaving interfaces with classes,
so that x.c = Object for every interface x.
Behaviour
(or Class or ClassDescription) creates a dangling class, (2) instantiating the class named
Metaclass creates a dangling metaclass, (3) a class can be made a direct inheritance descendant of its metaclass. The
superclass: method allows to change the superclass link to
point to (presumably) arbitrary non-terminal object so that cycles can arise.
r := ProtoObject. b := Behavior. c := Class. mc := Metaclass.
a := Behavior new.
m := Metaclass new.
Object subclass: #B.B superclass: (B class).
Behavior or of its descendants,
superclass: setter.
Metaclass,
which induces the corresponding imposed class map,
.ȼlass.
This map coincides with the standard .class
map except for implicit metaclasses,
where it redirectsthe value from the
Class class to the Metaclass class,
introducing monotonicity breaks with respect to inheritance.
Note that the class introspection method
does not correspond to .ȼlass but to
.aȼlass
(the imposed actualclass map)
which takes object actuality into account.
Another quirk that can be captured by an appropriate generalization
of the canonical structure is formed by additional twist links.
These are inheritance child-parent pairs (x.ec, c)
where x is a subsidiary
inheritance root –
a built-in parentless class other than r.
Each of Pharo and Squeak contains one such class,
named PseudoContext and ObjectTracer, respectively.
The helix chain contains 5 classes:
Class < ClassDescription
< Behavior < Object < ProtoObject = r
The Metaclass class is a sibling of the Class class.
Metaclasses can be defined as C.ȼlass.↧
– this makes Class and Metaclass the only explicit metaclasses.
Finally, the Ruby conditions apply:
single inheritance and single metalevel for classes.
Traits –
instances of the built-in Trait class.
Unlike in Ruby, the semantics of extended object membership, ϵ•,
is not reflected by the isKindOf: introspection method (as of Pharo 1.3).
As of GNUstep, there are (at least) 3 built-in inheritance roots,
named Object, NSObject and NSProxy.
Like in Smalltalk-80,
the Ruby conditions apply:
single inheritance and single metalevel for classes.
As a consequence of degeneracy,
metaclasses cannot be expressed as
C.class.↧ since this set contains all classes.
One possible solution is to simply define a metaclass as an object
on the metalevel 2 or higher (so that there are no explicit metaclasses).
redirectiontarget. As of CLISP 2.49, there are 8 helix classes:
class < clos::potential-class < …
< standard-object < T = r
The missing 4 classes do not form a chain in inheritance.
Like in Python, there are no additional constraints:
multiple inheritance is supported as well as creation of explicit metaclasses.
isa introspection method can be used both
to detect membership as well as inheritance.
As for metaclasses, we can apply the solution proposed to Objective-C and define metaclasses to be the objects on metalevel 2 or higher. Since Perl does not have any actual objects on these metalevels, there are no actual metaclasses.
In Perl, multiple inheritance is allowed.
The built-in class named UNIVERSAL stands for the
inheritance-root r.
However, the assumption is needed
that the @ISA variable of this class is not changed.
frontpart of the structure. We call objects from this substructure actual(s). In languages that do not support ϵ refined by implicit objects, the actual objects are exactly the primary ones. In general, some eigenclasses may also be actual.
Given a monotonic eigenclass structure (O, ϵ), possible subsets A of actual objects can be axiomatized as follows. (For a set X of objects, we let X.⋀ be the set of all strict upper bounds of X.)
twistpair of objects t, u such that u ≻ t ∈ R and u.↥ = A ∩ H. (That is, u is the unique inheritance parent of a metalevel top t, and u is the bottom of all actual helix objects.) Since A is a closure system in inheritance, there is a corresponding closure operator, .a, and the corresponding actualclass map, .aclass = .ec.a. For an object x, the actualclass of x is the least actual container of x.
In canonical structures, the .aclass map forms a tree (similarly to .class). The u object that is the bottom of A ∩ H belongs to the eigenclass chain of c (the instance / metaclass root) and is the unique fixpoint of .aclass (that is, u is the root of the actualclass tree). Observe also that
Note: In most cases (e.g. in the introductory sample), the blue arrows contained in the diagrams show the actualclass map. (In general, blue arrows have been used to display .aclass or .class or .class.↥ or .aȼlass.)
object definition.
In Smalltalk-80 and Objective-C, the set of actual eigenclasses equals
C.ec.
Ruby is the only language that supports dynamic eigenclass allocation.
Typically, for an object x,
the eigenclass x.ec becomes actual by defining
singleton
methods for x.
For efficiency, there are more allocated eigenclasses than those accessed
from the user code.
This induces 2 different extents of actuality,
as described before.
class.
Due to the metaclass redirection,
.aȼlass does not form a tree
but just a (directed) pseudotree with a 2-element cycle
containing the Metaclass class and its eigenclass.
Non-terminal objects in Dylan are called types []. The following table shows 3 supported kinds of types that have correspondence to basic structures.
Kind of Dylan types |
Our terminology | Evaluation | Instances of (via instance?) |
| Classes | <class> |
||
| Singletons | x.ɛɕ ↔ singleton(x) |
<singleton> |
|
| Subclass types [] | Powerclasses outside O.ɛϲ | x.ec ↔ subclass(x) |
<subclass> (⁎) |
Notes:
<subclass> class is not referenced by its name.
subclass(x)
is supported for every x that is a class.
singleton(x)
is supported for all objects x.
As a consequence, there cannot be a perfect correspondence between
singletons in Dylan and singletons in basic structures
since the latter ones are only defined for bounded objects.
singleton(x) or subclass(x)
(even when performed repeatedly with the same argument x)
returns a new object.
Such objects can be thought of as equivalent representants of a given
singleton or powerclass.
subtype? method.
The composition of blue arrows with inheritance
– object membership in Dylan –
is exactly what is detected
by the instance? method.
All powerclasses of classes
(i.e. all the supported powerclasses w.r.t. given set of classes)
are displayed.
In contrast, supported singletons are only shown for some objects.
let r = <object>; let ty = <type>; let c = <class>; let si = <singleton>; let lt = last(direct-superclasses(si)); let su = object-class(subclass(r)); let A = make(c); let B = make(c, superclasses: list(A)); let u = make(B);
lt
…
<limited-type>
su
…
<subclass>
Observations:
subclass typesin Dylan and metaclasses in Smalltalk-80.
| Dylan | Smalltalk-80 | |
| Powerclasses of classes (C.ec) are termed: | Subclass types | (Implicit) metaclasses |
| The (imposed) metaclass root ȼ is named: | <subclass> |
Metaclass |
| For a class x, the powerclass x.ec is evaluated by: | subclass(x) |
x class |
| The imposed class map .ȼlass is introspected by method: | object-class |
— |
| The imposed actualclass map .aȼlass is introspected by: | — |
class |
instance? method,
<singleton> and
singleton(<singleton>) are members of each other.
subclass types) can only have classes as members. As a consequence, (≤) ○ (.ec) ⊆ (ϵ) is not satisfied in general. For example,
u.ɛϲ
(the singleton of the terminal object u)
is from
B.↧ but not from B.ec.϶.
Formally, object membership with prototypes can be defined by combining eigenclasses and prototypes. In the specialized document [], S1ȷ structures are introduced as structures (Θ, O, ϵ) such that (Θ, ϵ) is a canonical eigenclass structure without terminal objects, and O is a subset of Θ such that the substructure (O, ϵ) is a canonical eigenclass 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.
var r, c, A, B, s, u, v; r = Object c = Function A = new c B = new c; B.prototype.__proto__ = A.prototype s = new A u = new B; v = new B
A.__proto__ = c.__proto__ = r; B.__proto__ = A
newinheritance root – the unique common ancestor of all objects (in contrast to r which is just a common root for non-zero metalevels).
__proto__,
constructor and prototype, respectively.
For an object x and a class y,
x.__proto__ is the inheritance parent of x,
x.constructor is the class of x,
y.prototype is the instance prototype of y.
constructor property is owned by prototypes and inherited by other objects.
In contrast, __proto__ and prototype are never (strictly) inherited.
The __proto__ property is non-standard.
When not supported, Object.getPrototypeOf(x) can be used for introspection.
The instance-of relation can be introspected via the instanceof operator,
except that y.prototype is not reported as an instance of y.
The Ruby conditions apply:
single inheritance between objects and single metalevel for classes.
In contrast to Ruby, Smalltalk or Objective-C,
JavaScript does not support parallel metalevel hierarchies.
Only inheritance between prototypes is supported, not between classes.
This is why we wrote .sc' instead of just .sc.
According to .sc', the inheritance parent of every class is
c.ce (Function.prototype).
However, the modification
(≤) → (≤') = (≤) ∖ (C, <)
has no impact to the instance-of relation:
we still have
(ϵ) = (≤') ○ (.class) = (≤') ○ (.ͼlass).
There are two helix classes:
Function < Object = r.
As the names constructor or Function suggest,
JavaScript uses another terminology for the class map or the class set.
In JavaScript, classes are constructors and also functions.
Every constructor is a function.
Functions are the Functions.
Except for c.ce and
for native built-in functions like eval or parseInt,
every function is also a constructor.
Being terminal instances of c, the
native built-in functions account for the relaxation of
(p~5).
Another deviation from the canonical structure is caused by the
built-in Function.prototype.bind method.
A constructor x created using this method shares its
instance prototype x.ce with the constructor
to which x is bound
(although x.ce is not obtained via x.prototype.)
The above description of the JavaScript native core structure
is only valid under
ideal circumstances which are not guaranteed
by the ECMAScript standard.
For example, the constructor or prototype properties
can be almost arbitrarily manipulated.
To ensure validity, additional restrictions have to be imposed on state transitions.
narrowdefinition can be characterized by the following features:
broaddefinition further generalizes the
narrowdefinition by only using those constraints that are imposed by RDFS axioms and entailments rules.
Notes and observations:
pointedclass p) are the primary ontological structures such that
broaddefinition, an RDFS core structure is a structure (Ō, ϵ, ≤C, ≤P, r, c, p) where Ō is the set of objects or resources, ϵ, ≤C, and ≤P are the instance-of, subclass-of and subproperty-of relations on Ō, respectively, and r, c, and p are distinguished objects. Instances of c form the set C of classes, instances of p form the set P of properties. The structure is subject to the following conditions:
narrowdefinition is obtained from the
broadone by defining the inheritance relation ≤ as the reflexive closure of (≤C) ∪ (≤P) and making the following assertions: (o~2)(b): (≤) ○ (ϵ) ⊆ (ϵ), (o~4): helix classes are …, (o~6): well-foundedness of ϵ on non-helix objects, (o~7)(b): C.ϵ ⊆ c.↥ ∪ c.↧, (o~9): c is a least helix class, and (o~10): p is not from c.↥ ∪ c.↧.
rdf:type
rdfs:subPropertyOf
rdfs:subClassOf
rdfs:Resource
rdfs:Class
rdf:Property
rdfs:Class < rdfs:Resource = r.
In addition to c, there is a second built-in metaclass,
rdfs:Datatype.
Note:
The diagram shows the built-in structure according to RDF 1.1 Semantics
[]
which adds
rdf:HTML and rdf:langString
as 2 new built-in instances of rdfs:Datatype
to the previous 2004 version [].
We can now define an RDFS core graph as an RDF graph (Ō, Ψ) such that the following holds:
There are entailment rules that refer to distinguished objects
not considered in the above description.
(In particular, the rdfs:domain and rdfs:range properties.)
As a consequence,
some of our RDFS core graphs are in fact not allowed by RDF Schema.
However,
RDF Schema still only guarantees the conformance to the broad
definition
of ontological structure of ϵ.
None of
(o~2)(b),
(o~4),
(o~6),
(o~7)(b)[],
(o~9), or
(o~10) is asserted.
narrowand
broadstructures are asserted.
owl:Class, rdfs:Class} <
{owl:Thing, rdfs:Resource}.
which indicates that RDFS helix classes have their OWL equivalents.
Similarly, rdf:Property is equivalent to owl:ObjectProperty
and the metaclass rdfs:Datatype
is equivalent to (the metaclass) owl:DataRange.
In total, there are 7 built-in
descendants of rdfs:Class.
However, one of them, owl:Nothing, is special since
it is asserted to
(a) be a descendant of all classes and
(b) to have no instances.
That is, owl:Nothing is meant to be an abstraction of the empty set.
As a consequence, owl:Nothing is not regarded as a metaclass
(cf. []).
There is still single inheritance between non-equivalent objects other
than owl:Nothing.
Single classification is not preserved (not even up to equivalence)
due to common instances of
owl:AnnotationProperty and
owl:OntologyProperty.
The restriction of inheritance to RDF(S) vocabulary is the same as
inheritance in the built-in RDFS core structure.
The restriction of instance-of is almost the same:
the rdfs:Literal class is made an instance of rdfs:Datatype
by a single additional axiomatic triple
[].
| This document | Type-theoretic setting [] | ||
| Terminology | Notation | Notation | Terminology |
| Inheritance | ≤ | ≤ / ⊆ / <: |
Subtyping |
| Object membership | ϵ | : | Typing |
| Powerclass map | .ec | Power() | Power type operator |
| Terminal objects | T | Values | |
| Non-terminal objects | ⅽ.϶ | Types | |
| Top of metalevel 2 | ⅽ | Type | Type of types |
Notes:
y being a non-trivial partition of xis a special case of
x being a non-member union of y, the semantic shift can be diagrammatized by