CS 342 Lecture -*- Outline -*- * Inheritance ** Hierarchy of classes Stack is subclass of Object, superclass of Stack is Object inherits methods + data in Little smalltalk subclass cannot access instance vars of super ** Example: Adding size to stacks ---------- Stack addSubClass: #SizedStack instanceVariableNames: 'size' "methods" new super new. size <- 0 push: anElem size <- size + 1. super push: anElem pop size <- size - 1. super pop size ^size ---------- *** Inheriting data Show the layout of storage in instances of SizedStack *the Stack is not contained in the SizedStack (that would be a different design) *** Inheriting operations Explain meaning of self and super -infinite loops from calling with self Steps in message sending: receiver = object that is sent message 1. let c be class of receiver (or superclass if receiver was named "super") 2. look for method in class c (a) if found: go to step 3 (b) otherwise: let c be superclass of c. goto 2. errors: found when reach Object, dynamic type checking 3. bind self to receiver and actuals to formals, alloc temps, bind super to receiver 4. execute the code of the method ** Example: CachedStack ---------- Stack addSubClass: #CachedStack instanceVariableNames: 'cache' *instance methods new is inherited push: anElem (cache notNil) ifTrue: [super push: cache]. cache <- anElem pop (cache isNil) ifTrue: [super pop] ifFalse: [cache <- nil]. top (cache notNil) ifTrue: [^cache] ifFalse: [^super top] isEmpty ^(cache isNil) and: [super isEmpty] ---------- ------------ "example of use" c <- CachedStack new. c push: 1. c push: 2 ------------ *** How to define printString? inherit it? following works in ST-80, but accesses elems instance variable (coupling between super and subclass) illegal in LST --------- "following is illegal in Little Smalltalk as a method of CachedStack" printString | s | s <- 'Stack ('. (cache notNil) ifTrue: [s <- s , ' ' , cache printString]. elems do: [ :e | s <- s , ' ' , e printString]. ^ s , ' )' ---------- would like to inherit it *** Inheriting printString by factoring out common parts ------ "instance methods for Stack" printString ^ 'Stack(' , self printStringElements , ')' printStringElements | s | s <- ''. elems do: [ :e | s <- s , ' ' , e printString]. ^s ------ ------ "instance method for CachedStack" printStringElements | s | s <- ''. (cache notNil) ifTrue: [s <- s , ' ' , cache printString]. s <- s , super printStringElements. "*could have referenced elems here in ST-80" ^s ----- conclusion: subclassing allows code sharing abstraction ** Single vs. multiple inheritance e.g., what if want SizedCachedStack? *** Single inheritance Inheritance is hierarchical (tree like) in ST. SizedCachedStack has to be subclass of either Sized or Cached (Class hiererchy is exactly parallel Stack class inherits from Object class = Class) *** Multiple inheritance (in CLOS) class can be subclass of many superclasses problems: what if two (or more) define same instance variable or same method? efficiency (have to hash to get instance vars)