Smalltalk Lecture 9
1
Metaclasses in 7 points
1. Every object is an instance of a class
2. Every class eventually inherits from Object
3. Every class is an instance of a metaclass
4. The metaclass hierarchy parallels the class hierarchy
5. Every metaclass inherits from Class and Behavior
6. Every metaclass is an instance of Metaclass
7. The metaclass of Metaclass is an instance of Metaclass
2
1. Every object is an instance of a class
3
2. Every class inherits from Object
> Every object is-an Object =
— The class of every object ultimately inherits from Object
aSnakeSquare is-a SnakeSquare and is-a BoardSquare
and is-an Object
Caveat: in some Smalltalk systems, Object has a superclass called ProtoObject
4
The Meaning of is-a
> When an object receives a message, the method is looked up in the method dictionary of its class, and, if necessary, its superclasses, up to Object
5
Responsibilities of Object
> Object
— represents the common object behavior
– error-handling, halting …
— all classes should inherit ultimately from Object
6
3. Every class is an instance of a metaclass
> Classes are objects too!
— Every class X is the unique instance of its metaclass, called X class
7
Metaclasses are implicit
> There are no explicit metaclasses
— Metaclasses are created implicitly when classes are created — No sharing of metaclasses (unique metaclass per class)
8
Metaclasses by Example
SmallInteger
Integer
Set (LargePositiveInteger LargeNegativeInteger LargeInteger SmallInteger LargeZeroInteger) false
true
Set (#binomial: #truncated #anyMask: #digitAt: #clearBit: #ceilingLog: #timesRepeat: #numerator #denominator #hash #printPaddedWith:to:base: #printPaddedWith:to: #gcd: #setBit: #noMask: #bitClear: #ceiling #lcm: #storeOn:base: #isBitSet: #even #estimatedLog #printOn: #printStringRadix: #storeString #floor #replace:withStringBase: #storeLiteralOn: #rounded #factorial #allMask: #floorLog: #coerce: #odd #isInteger #displayString #printString #printOn:paddedWith:to:base: #bitAt: #bitInvert #highBit #alignTo: #printOn:paddedWith:to: #asCharacter #displayOn: #printOn:base: #printString: #isRational #bitAt:put: #asFraction #asScaledDecimal: #radix: #lowBit #storeOn: #isLiteralObject )
345 class
SmallInteger superclass
Integer allSubclasses
Integer canUnderstand: #append: Integer canUnderstand: #binomial: Integer selectors
Class methods are instance methods of the metaclass.
Class variables are NOT instance variables of the metaclass.
Class instance variables are a new concept not found in C++/Java.
9
4. The metaclass hierarchy parallels the class hierarchy
10
Uniformity between Classes and Objects
> Classes are objects too, so …
— Everything that holds for objects holds for classes as well
— Same method lookup strategy
– Look up in the method dictionary of the metaclass
back: is a Snake constructor method
11
5. Every metaclass inherits from Class and Behavior
Every class is-a Class =
—The metaclass of every class inherits from Class
12
Where is new defined?
13
Responsibilities of Behavior
> Behavior
— Minimum state necessary for objects that have instances.
— Basic interface to the compiler.
— State:
– class hierarchy link, method dictionary, description of instances
(representation and number)
— Methods:
– creating a method dictionary, compiling method
– instance creation (new, basicNew, new:, basicNew:)
– class hierarchy manipulation (superclass:, addSubclass:)
– accessing (selectors, allSelectors, compiledMethodAt: )
– accessing instances and variables (allInstances, instVarNames)
– accessing class hierarchy (superclass, subclasses)
– testing (hasMethods, includesSelector, canUnderstand:, inheritsFrom:, isVariable)
14
Responsibilities of ClassDescription
> ClassDescription
— adds a number of facilities to basic Behavior:
– named instance variables
– category organization for methods
– the notion of a name (abstract)
– maintenance of Change sets and logging changes
– most of the mechanisms needed for fileOut
— ClassDescription is an abstract class: its facilities are intended for inheritance by the two subclasses, Class and Metaclass.
15
Responsibilities of Class
> Class
— represents the common behavior of all classes
– name, compilation, method storing, instance variables …
— representation for classVariable names and shared pool variables (addClassVarName:, addSharedPool:, initialize)
— Class inherits from Object because Class is an Object
– Class knows how to create instances, so all metaclasses should inherit ultimately from Class
16
6. Every metaclass is an instance of Metaclass
17
Metaclass Responsibilities
> Metaclass
— Represents common metaclass Behavior
– instance creation (subclassOf:)
– creating initialized instances of the metaclass’s sole instance
– initialization of class variables
– metaclass instance protocol (name:inEnvironment:subclassOf:….)
– method compilation (different semantics can be introduced)
– class information (inheritance link, instance variable, …)
18
7. The metaclass of Metaclass is an instance of Metaclass
19
Class Instance Variables
> Class are objects too
— Instances of their metaclass
– Methods looked up in the method dictionary of their metaclass — Can also define instance variables
> When a metaclass defines a new instance variable, then its instance (a Class) gets a new variable
— I.e.,inadditiontosubclass,superclasses,methodDict…
> Use class instance variables to represent the private state of the class
— E.g., number of instances, superclass, etc.
– Be sure to distinguish whether you need a class variable or an instance variable or a class instance variable.
20
Example: the Singleton Design Pattern
> A class with only one instance
— We keep the unique instance created in an instance variable
WebServer class
instanceVariableNames: ‘uniqueInstance’
WebServer class>>new
self error: ‘Use uniqueInstance to get the unique instance’
WebServer class>>uniqueInstance uniqueInstance isNil
ifTrue: [uniqueInstance := self basicNew initialize].
^ uniqueInstance
21
Class Variable = Shared Variable
> To share information amongst all instances of a class, use a “class variable”
— Shared and directly accessible by all the instances of the class and subclasses
— Accessible to both instance and class methods — Begins with an uppercase letter
22
Initializing class variables
> Class variables should be initialized by an initialize method on the class side, or by lazy initialization
Magnitude subclass: #DateAndTime.
DateAndTime instanceVariableNames: ‘seconds offset jdn nanos’. DateAndTime addClassVarName: ‘LocalTimeZone’.
Date class>>localTimeZone “Answer the local time zone”
^ LocalTimeZone ifNil: [ LocalTimeZone := TimeZone default ]
23
Instance Variables vs. Class Variables vs. Class Instance Variables
24
Reflection, Introspection, Intercession, Reification (Meta-programming)
> Reflection is the ability of a program to manipulate as data something representing the state of the program during its own execution.
— Introspection is the ability for a program to observe and therefore reason about its own state.
— Intercession is the ability for a program to modify its own execution state or alter its own interpretation or meaning.
> Reification is the mechanism for encoding execution state as data
25
The Essence of a Class
1. A format
— I.e., a number of instance variables and types
2. A superclass
3. A method dictionary
26
Behavior class>> new
> In Pharo:
Behavior class>>new
| classInstance |
classInstance := self basicNew. classInstance methodDictionary:
classInstance emptyMethodDictionary. classInstance superclass: Object. classInstance setFormat: Object format. ^ classInstance
NB: not to be confused with Behavior>>new!
27
The Essence of an Object
1. Class pointer
2. Values
> Can be special:
— SmallInteger
— Indexed rather than pointer values
— Compactclasses(CompiledMethod,Array…)
28
Metaobjects vs metaclasses
> Need distinction between metaclass and metaobject!
— A metaclass is a class whose instances are classes
— A metaobject is an object that describes or manipulates other objects
– Different metaobjects can control different aspects of objects
29
Some MetaObjects
> Structure:
— Behavior,ClassDescription,Class,Metaclass,ClassBuilder
> Semantics:
— Compiler,Decompiler,IRBuilder
> Behavior:
— CompiledMethod,BlockContext,Message,Exception
> ControlState:
— BlockContext,Process,ProcessorScheduler
> Resources: — WeakArray
> Naming:
— SystemDictionary
> Libraries:
— MethodDictionary, ClassOrganizer
30
Accessing state
> Object>>instVarNamed: aString
> Object>>instVarNamed: aString put: anObject
> Object>>instVarAt: aNumber
> Object>>instVarAt: aNumber put: anObject
pt := 10@3.
pt instVarNamed: ‘x’.
pt instVarNamed: ‘x’ put: 33.
pt
10 33@3
31
Accessing meta-information
> Object>>class
> Object>>identityHash
‘hello’ class
(10@3) class
Smalltalk class
Class class
Class class class Class class class class
‘hello’ identityHash
Object identityHash
5 identityHash
ByteString
Point
SystemDictionary
Class class
Metaclass
Metaclass class
2664 2274 5
32
Code metrics
Collection allSuperclasses size. Collection allSelectors size. Collection allInstVarNames size. Collection selectors size. Collection instVarNames size. Collection subclasses size. Collection allSubclasses size.
2192 053
043
33
Recap: Classes are objects too
> Object
— Root of inheritance — Default Behavior — Minimal Behavior
> Behavior
— Essence of a class
— Anonymous class
— Format, methodDict, superclass
> ClassDescription
— Human representation and organization
> Metaclass
— Sole instance
34
Classes are Holders of CompiledMethods
35
Invoking a message by its name
Object>>perform: aSymbol Object>>perform: aSymbol with: arg
> Asks an object to execute a message — Normal method lookup is performed
5 factorial
5 perform: #factorial
120 120
36
Executing a compiled method
CompiledMethod>>valueWithReceiver:arguments: > No lookup is performed!
(SmallInteger>>#factorial)
valueWithReceiver: 5
withArguments: #()
(Integer>>#factorial)
valueWithReceiver: 5
withArguments: #()
Error: key not found
120
37
Example of class initialization
> Magnitude subclass: #Date
> instance variable names: — day
— year
> classVariableNames: — DaysInMonth
— FirstDayOfMonth
— MonthNames
— SecondsInDay — WeekDayNames
38
Date class>>initialize
> > >
> > > > > > >
Date class>>initialize
“Initialize class variables representing the names of the months and
days and the number of seconds, days in each month, and first day of each month. ”
MonthNames := #(#January #February #March #April #May #June #July #August #September #October #November #December ).
SecondsInDay := 24 * 60 * 60. DaysInMonth:=#(312831303130313130313031). FirstDayOfMonth := #(1 32 60 91 121 152 182 213 244 274 305 335 ). WeekDayNames := #(#Monday #Tuesday #Wednesday #Thursday
#Friday #Saturday #Sunday )
39