Author
|
Document date
|
classesand which are
metaclasses. More specifically, there is no standard terminology (known to the author) that clearly states whether
metaclassesis a subset of the set of
classes(i.e. each metaclass is a class).
metaclassesis disjoint from the set of
classes(i.e. a metaclass is not a class and vice versa).
metaclasses
⊂
classes
Metaclass
class is not a metaclass.
Metaclass
instances.)
(*) Note that this definition is incorrect: It implies that all non-instantiable classes are metaclasses.
metaclasses
∩
classes
== ∅
the-class-ofcorresponds to the map between objects. This map is established by a method called
class
.
(Using the Smalltalk syntax, the value for an object x
is
obtained by x class
class
method yields the opposite of (∗):
metaclasses are in one-to-one correspondence with classes[] or that
each classis
an instance of its own metaclass[], both Smalltalk's two major implementations, Pharo and Squeak, allow counter-examples to these statements. The following are the two main counter-examples (note that they are not based on the terminological ambiguity):
m := Metaclass new
creates an object m
that is reported as
Object
(according to m superclass == Object
Metaclass
(according to m class == Metaclass
thisClass
is nil
.
c := Class new
creates a class
(again, it is reported as a direct subclass of Object
)
such that c class == Class
Class
class is reported as the corresponding metaclass for
c
.
superclass
links
is neither acyclic nor single rooted in the general case.
superclass:
method allows creation of cycles.
For classes X
, Y
, the code
X superclass: X
makes X
its own superclass,
X superclass: Y. Y superclass: X
lets X
and Y
be superclasses of each other.
ProtoObject
class,
there is at least one other class x
such that
x superclass == nil
PseudoContext
class in case of Pharo,
ObjectTracer
class in case of Squeak.
x
satisfies
the twistcondition (just like
ProtoObject
), namely that
x class superclass == Class
.
implicit metaclassto
metaclasswhere the adjective
implicitis present in the tooltip. This allows us to assume (B) – i.e.
actualclassinstead of
class. Specifically:
.aclass
(instead of just .class
)
for the Smalltalk's the-class-ofmap.
x.aclass == y
then we call y
the actualclass
of x
instead of just the classof
x
.
the-class-ofmap corresponds to Ruby's actualclass map rather than to the Ruby's class map.
We also perform the following preparation
for a rubyfication
of Smalltalk's object model:
y
created via
y := x new
x
is an inheritance descendant of the Behavior
class (including the Behavior
class itself).
Class
and Metaclass
,
i.e.
we assume that
Class
class has no subclasses.
(The only superclass link to Class
is allowed from ProtoObject class
Metaclass
class has no subclasses.
PseudoContext
or ObjectTracer
.
(Oa, .terminative?, .primary?)
where
Oa
is a finite set of actual objects.
.terminative?
is a boolean attribute of objects indicating
whether an object is terminative.
.primary?
is a boolean attribute of objects indicating
whether an object is primary.
(SmT0~1) |
All terminative actual objects are primary,
i.e. there are no terminative eigenclasses in Oa .
|
Using the 2x2 Ruby nomenclature from
[],
the structure can be diagrammatized as follows.
In particular, the set Oa
is partitioned into
terminals, classes and metaclasses.
Primary objects |
First eigenclasses |
||
Classive objects
alias Classives |
Classes |
Metaclasses |
|
Terminative objects
alias Terminatives |
Terminals |
Eigenclasses of terminals |
Note:
Note: An alternative title of this section is: The superclass and actualclass maps.
An SmT1 structure is an SmT0 structure equipped with(.sc, .aclass, r, Metaclass)
where
.sc
is a partial function between objects,
x.sc
(if defined) is called the superclass of x
.
.aclass
is a total function between actual objects,
.aclass
is called the actualclass of
x
.
r
is an object, called the inheritance root.
Metaclass
is an object.
We call it the primary actualclass root.
Metaclass.aclass
is then the secondary
actualclass root.
x.sc(i)
(resp. x.aclass(i)
)
denotes the i
th application of .sc
(resp. .aclass
)
to x
.
.sc
is denoted ℍ
and called the (.sc
-) inheritance.
(SmT1~1) |
The inheritance ℍ
is an algebraic tree on non-terminals, its root is r .
We denote by x.hancs
the list of
sc -inheritance ancestors of x ,
starting with x and ending with r .
We also let x.hancestors be x.hancs without
metaclasses.
|
(SmT1~2) |
For the actualclass map .aclass the following hold:
Metaclass object the following holds:
|
(SmT1~3) |
.sc and .aclass are commutative in the following sense:
If(Using (SmT1~4): The .sc -inheritance on metaclasses is parallel to
the .sc -inheritance on
classes.)
|
(SmT1~4) |
.sc preserves being a class.
|
(SmT1~5) | No correspondent to Ruby's (S1~5) |
(SmT1~6) | No correspondent to Ruby's (S1~6) |
(SmT1~7) |
The list r.aclass.sc.hancs contains
exactly n classes, called helix classes,
where
n is at least 2 .
|
(SmT1~8) |
|
(SmT1~9) |
Metaclass and Class
are siblings in the sc -inheritance, i.e.
|
Proposition:
x.aclass(1) == Metaclass
for every metaclass x
.
x.aclass(2) == Metaclass
for every class x
,
x.aclass(3) == Metaclass
for every terminal x
.
(Oa, .aclass)
is a pseudotree with
the pseudoroot being
the 2-element set { Metaclass, Metaclass.aclass }
.
We call this pseudotree the actualclass pseudotree.
Its levels are described by the following table.
level members | ||
0 (top level) | { Metaclass, Metaclass.aclass } |
|
1 | Metaclasses except Metaclass.aclass |
|
2 | Classes except Metaclass |
|
3 | Terminals |
Note: The Ruby's actualclass map is obtained by redirecting blue arrows to .
.class
map,
the Smalltalk's real class map, denoted .rclass
,
maps objects to classes.
It is defined as follows:
x.rclass == x.aclass
if x
is terminal or a
metaclass,
x.rclass == Class
otherwise (i.e. if x
is a class).
Proposition:
x
, x.rclass
equals
the first member of the ancestor list x.aclass.hancs
that is a class,
i.e.
x.rclass == x.aclass.hancestors[0]
.
(Oa, .rclass, Class)
is an algebraic tree of depth 2.
.rclass
replaced by .class
and
Oa
replaced by O
).
The only difference is that the real class of all Smalltalk's
metaclasses is
the Metaclass
class whereas in Ruby,
the class of all eigenclasses is the Class
class.
The structure (Oa, .rclass, Class)
can be diagrammatized as follows.
Note: The Ruby's class map is obtained by redirecting blue arrows to .
.aclass ◦ ℍ
.
Equivalently,
x
is kind of y
iff x.aclass.hancs
contains y
.
.rclass ◦ ℍ
.
Equivalently,
x
is an instance of y
iff
the real class of x
is a (possibly indirect) subclass of y
or is y
itself.
x.rclass == y
then we say that
x
is a direct-instance-of y
.
Proposition:
Note:
We deviate here from the common definition in Smalltalk which states that the instance-of relation is exactly the actualclass pseudotree, i.e.x
is an instance of y
iff
x.aclass == y
.
Our definition yields the following advantages:
instances of y
instead of subinstances of y
or
instances of subclasses of y
.
Class
class.
(Unfortunately, this is not as much an advantage as it would be
if we were allowed to create classes by Class new
.)
A
is a class, then by A
s
we mean the set of all instances of A
.
The following proposition shows that there is at least one advantage of the Smalltalk object model over the Ruby object model.
Proposition:
Class
es.
Metaclass
es.
Rubyficationof SmT1 is performed by adding fictitious eigenclasses of terminals. This can be schematized by
|
→ |
|
(O₀₁, .ec)
where
O₀₁
is a (finite) superset of the set
Oa
of actual objects.
Elements of O₀₁
are called
SmT1R-objects or just objects,
elements of O₀₁ ∖ Oa
are non-actual(s).
The 2x2 nomenclature
is still applied: Non-actual objects together with metaclasses form
the set of secondary objects, also called (first) eigenclasses.
.ec
is a one-to-one map between primary and secondary objects,
x.ec
is called the eigenclass of x
.
(SmT1R~1) |
In the restriction to classes,
the eigenclass map .ec
coincides with the actualclass map .aclass .
|
.ce
the inverse of .ec
and
extend the following maps to non-actual objects x
:
.sc
by x.sc == x.ce.aclass
,
.aclass
by
x.aclass == x.sc.ec
,
.rclass
by
x.rclass == Class
(thus eigenclasses of terminals are NOT Metaclass
es).
Proposition A:
(O₀₁, .sc, .ec)
is a Ruby S1₀₁ structure
(up to the number of helix classes).
.class
,
restricted to O₀₁
.
Oa
defines an actuality
(corresponding to an indicator function .actual?
)
that has Smalltalk extent.
.aclass
,
restricted to O₀₁
.
Proposition B:
.rclass
map coincides with Ruby's .class
map.
Specifically,
x.rclass == Metaclass
and x.class == Class
if
x
is a metaclass,
x.rclass == x.class
otherwise.
.aclass
map coincides with Ruby's .aclass
.
Specifically,
x.aclass == Metaclass
and x.aclass == Class.ec
if
x
is a metaclass,
x.aclass == x.aclass
otherwise.
Terminology | Smalltalk | Ruby | ||
Smalltalk expression | Our expression | Our expression | Ruby expression | |
the superclass of a non-terminal x |
x superclass |
x.sc |
x.superclass |
|
the eigenclass of x |
x.ec |
x.singleton_class (limited use) |
||
the actualclass / actualclass of x |
x class |
x.aclass |
x.aclass |
|
the (real) class of x |
x class class == Metaclass ifTrue: Class ifFalse: x class |
x.rclass |
x.class |
x.class |
the class sideof a metaclass x (†) |
x thisClass |
x.ce |
Internally, x.ce is referenced by
an internal instance variable __attached__ |
|
inheritance ancestors of a non-terminal x |
{x}, x.allSuperclasses |
x.hancs |
Obtainable by following .superclass links. |
|
classes that are inheritance ancestors of x |
Obtainable by removing metaclasses from {x}, x.allSuperclasses |
x.hancestors |
x.ancestors - x.included_modules |
|
x 's actualclass
/ actualclass is y ? |
x isMemberOf: y |
x.aclass == y |
x.aclass == y |
|
x direct-instance-of y ? |
x class class == Metaclass ifTrue: y == Class ifFalse: x class == y |
x.rclass == y |
x.class == y |
x.class == y |
x instance-of y ? |
y class class == Metaclass & x isKindOf: y |
(x,y) ∈ |
(x,y) ∈ |
x.class ≤ y && y.class == Class |
x kind-of y ? |
x isKindOf: y |
(x,y) ∈ |
(x,y) ∈ |
x.kind_of? y && y.kind_of? Class (*) |
is x terminal? |
x class class ~= Metaclass & x class ~= Metaclass |
x.class != Class |
||
is x a class? |
x class class == Metaclass |
x.class == Class && x == x.ancestors[0] |
||
is x a metaclass? |
x class == Metaclass |
Class == x.class && !!(Class > x)
(**)
|
Notes:
class sidewe mean
primary sidehere. Note that in general there is an ambiguity with the
class sideterm:
classversus
metaclasscontext, it appears on the primary side.
instance methodsversus
class methodscontext, it appears on the secondary side.
y.kind_of? Class
disallows modules y
.
This corresponds to the range-restriction of Ruby's fullkind-of,
.aclass ◦ ≤
.aclass ◦ ℍ
Class > x
indicates that we are concerned by implicit metaclasses here.
the-class-ofmap to the
actualclassmap. This change in terminology can be justified by the argument that
realclass map should be a many-to-one mapping without any part that has enforced one-to-one characteristics.
the-class-ofmap is NOT a real class map. Instead, we consider the real class map to be
.rclass
,
which is the Ruby's class map except for the value on metaclasses.
In .rclass
, classes are mapped constantly to the Class
class,
so that they are not mapped to metaclasses.
This means that
The standard definition of a metaclass [] [] applies to explicit metaclasses:
Class
class.
This also means that
the Smalltalk's Metaclass
class is neither explicit nor implicit metaclass.
Definition and Application of Metaclasses, Proceedings of the 12th International Conference on Database and Expert Systems Applications, Springer-Verlag 2001, http://cs.ulb.ac.be/publications/P-01-01.pdf | ,|
Putting Metaclasses to Work, Addison Wesley 1998 | ,|
Smalltalk-80: The Language and Its Implementation, Addison Wesley 1983, http://stephane.ducasse.free.fr/FreeBooks/BlueBook/Bluebook.pdf | ,|
Smalltalk and Object Orientation: An Introduction, Springer Verlag 1997, http://stephane.ducasse.free.fr/FreeBooks/STandOO/Smalltalk-and-OO.pdf | ,|
The Ruby Object Model: Data Structure in Detail, 2012, http://www.atalon.cz/rb-om/ruby-object-model | ,|
Wikipedia: The Free Encyclopedia, http://wikipedia.org |
February | 10 | 2012 | The initial release. |
April | 5 | 2012 | Minor additions and corrections. |
June | 21 | 2012 | Enhanced terminology for metaclasses (distinguishing between explicit a implicit). |