I. Smalltalk A. Message expression syntax 1. Basic expressions a. Identifiers ------------------------------------------ SMALLTALK: IDENTIFIERS Identifier Conventions Upper case: ClassNames lower case: instancevar Pseudo Variables self, super, smalltalk Special Names Instances: true, false, nil Classes: True, False, UndefinedObject Case matters: True (the class) vs. true (the instance) ------------------------------------------ b. Literals ------------------------------------------ LITERALS 3 30.45 $a "the character a" 'a string, don''t laugh!' #aSymbol #aSymbol:composed:ofKeywords: #* "also a symbol" #(1 2 3) "an array constant" #(foo bar 'and me') ------------------------------------------ 2. messages ------------------------------------------ KINDS OF MESSAGES Unary messages: 1 negated theta sin Pen new home green Binary messages: 3 + 4 5 - 4 * 2 (sum / count) * (reserve amount) Keyword messages: 3 max: 2 anArray at: 2 put: 3 (anArray at: 2) at: 3 ------------------------------------------ 3. Parsing ------------------------------------------ PRECEDENCE unary highest (most tight) binary keyword lowest (least tight) ASSOCITIVITY IS LEFT TO RIGHT 4 - 5 * 3 is (4 - 5) * 3 2 * theta sin is 2 * (theta sin) frame width: otherFrame width * 2 is frame width: ((otherFrame width) * 2) FOR YOU TO DO Parenthesize the following: foo at: 2 negated put: 4 + 3 * 2 negated ------------------------------------------ B. Blocks (closures) 1. statically scoped ------------------------------------------ BLOCKS Block = Examples: [ i print ] [ k <- k+1. k print. k ] [ :x :y | (x+y) print ] FOR YOU TO DO What is (a) printed and (b) returned by: [ :y | (y + 2) print. y ] value: 4 ------------------------------------------ C. Control Structures ------------------------------------------ CONTROL STRUCTURES (x > y) ifTrue: [x print] ifFalse: [y print] (x > y) and: [y > z] [i > 0] whileTrue: [i print. i <- i - 1] 3 timesRepeat: [4 print] ((1 to: 5) step: 2) do: [:i | i print] ------------------------------------------ ------------------------------------------ FOR YOU TO DO 1. Write a statement that prints the numbers from i to 10 in ascending order. 2. Write a statement that prints all the numbers in a set s that are greater than 3 s do: ------------------------------------------ D. Classes 1. Stack example ------------------------------------------ MAKING A CLASS > Object addSubClass: #Stack \ instanceVariableNames: 'elems' Object > Stack display Class Name: Stack SuperClass: Object Instance Variables: elems Subclasses: Stack TO ADD METHODS > Stack addMethod ------------------------------------------ ------------------------------------------ "methods for Stack" new elems <- List new push: anElement elems addFirst: anElement pop elems removeFirst isEmpty ^ elems isEmpty top ^ elems first printString "would be 'contents' in ST-80" | s | s <- 'Stack ('. elems do: [ :e | s <- s , ' ', e printString]. ^ s , ' )' ------------------------------------------ 2. Exercise ------------------------------------------ FOR YOU TO DO Complete the following class for a counter > Object addSubClass: #Counter \ instanceVariableNames: ' ' "methods for Counter" new increment value printString ------------------------------------------ E. object creation in little smalltalk ------------------------------------------ OBJECT CREATION IN LITTLE SMALLTALK How Stack new executes 1. send the "new" message to the class object "Stack" This: - creates - sets instance variables to 2. The new instance is sent the message ------------------------------------------ F. Semantics of variables, assignment, and mutation 1. object identity ------------------------------------------ OBJECT IDENTITY objects have an identitity = state = EXAMPLE s <- Stack new. s push: 1. s push: (Stack new push: 2). s push: s ------------------------------------------ 2. mutable vs. immutable ------------------------------------------ MUTABLE vs. IMMUTABLE OBJECTS def: an object is *mutable* if otherwise an object is *immutable* ------------------------------------------ are integers mutable in smalltalk? 3. variables and assigment ------------------------------------------ VARIABLES AND ASSIGNMENT def: a variable in Smalltalk is EXAMPLE p1 <- p2 like Pascal: var p1, p2: Point; { a pointer!} new(p); new(p2); p1 := p2. or C: typedef PointStruct * Point; Point p1, p2; ... p1 = p2; ------------------------------------------ Does an assigment copy the object in Smalltalk? What kind of value is in a Smalltalk variable? II. Inheritance A. Hierarchy of classes B. Example: Adding size to stacks ------------------------------------------ SIZED STACK > Stack addSubClass: #SizedStack \ instanceVariableNames: 'size' "methods for SizedStack" new ------------------------------------------ 1. Inheriting data 2. Inheriting operations ------------------------------------------ STEPS IN MESSAGE SENDING let receiver = object that is sent message let static-class = class where code being executed is defined let rc = if receiver is not super, then receiver's (dynamic) class else if receiver is "super" then superclass of static-class 1. [fetch] look for method in class rc (a) if found: (b) if not found and rc is not Object: (c) if not found and rc is Object: 2. [execute] bind self to bind super to bind formals to allocate temporary vars (|temp|), execute the code of the method ------------------------------------------ a. semantic examples without super ------------------------------------------ MESSAGE PASSING EXAMPLE > Object addSubClass: #C \ instanceVariableNames: '' > C addSubClass: #D \ instanceVariableNames: '' "methods for class C" m1 ^self m2 m2 ^ #C "methods for class D" m2 ^ #D ------------------------------------------ what is the result of x <- D new. x m1 ? b. semantic examples with super ------------------------------------------ MESSAGE PASSING EXAMPLE WITH SUPER > Object addSubClass: #C \ instanceVariableNames: '' > C addSubClass: #D \ instanceVariableNames: '' "methods for class C" m1 ^ self m2 m2 ^ 'C' m3 ^ 'm3' "methods for class D, subclass of C" m2 ^ super m3 m3 ^ 'E' ------------------------------------------ What is the result (if any) of the expression "C new m1"? What is the result (if any) of the expression "(D new) m1"? C. Example: CachedStack ------------------------------------------ CACHED STACK > Stack addSubClass: #CachedStack \ instanceVariableNames: 'cache' "methods for CachedStack" ------------------------------------------ 1. How to define printString? Smalltalk's read-eval-print uses printString ------------------------------------------ INHERITING PRINT METHODS printString for CachedStack "following is bad style, but works" printString | s | s <- 'Stack ('. (cache notNil) ifTrue: [s <- s , ' ' , cache printString]. elems do: [ :e | s <- s , ' ' , e printString]. ^ s , ' )' problems with the above: - ------------------------------------------ 2. Inheriting printString by factoring out common parts ------------------------------------------ INHERITANCE BY FACTORING OUT COMMON PARTS "methods for Stack" printString ^ 'Stack(' , self printStringElements , ')' printStringElements | s | s <- ''. elems do: [ :e | s <- s , ' ' , e printString]. ^s FOR YOU TO DO Define whatever methods are *needed* to have printString work for CachedStack ------------------------------------------ D. exercise Can you write Gague, like Counter, but also has a decrement method? E. Design issue: Single vs. multiple inheritance ------------------------------------------ SINGLE VS. MULTIPLE INHERITANCE def: a language has *single inheritance* if each class has def: a language has *multiple inheritance* if each class may have Motivating problem: what if want SizedCachedStack? ------------------------------------------ III. programming in Smalltalk A. factoring 1. factoring behavior so relevant parts can be inherited 2. abstract classes 3. using message passing instead of tests in code can you program this? B. protocols and polymorphism What's the language design tradeoff here? C. subtype vs. subclass How does C++ handle this? D. encapsulation vs. inheritance should Rectangle (which can be rep. by 2 points) or be a subclass of Point? E. dealing with binary operations 1. coerce to common type 2. double dispatching 3. equality: name carries point of view what should = mean in an OOP like Smalltalk? F. dealing with mutable objects