370 likes | 548 Views
Collections. Inheritance Polymorphism. Collection. 74 subclasses of Collection in Squeak 3.10 Some are abstract SequenceableCollection ArrayedCollection Most are concrete - Array, Bag, Dictionary, Interval, String, Set, Symbol. Collection as an Abstract Class.
E N D
Collections Inheritance Polymorphism
Collection • 74 subclasses of Collection in Squeak 3.10 • Some are abstract • SequenceableCollection • ArrayedCollection • Most are concrete - Array, Bag, Dictionary, Interval, String, Set, Symbol Object-oriented Programming and Design - Johnson & Yoder - Day 3
Collection as an Abstract Class • Collection has no instance variables. • Collection defines as subclassResponsibility • do: • add:, remove: (Changeable) • at:, at:put: (Sequenceable) Object-oriented Programming and Design - Johnson & Yoder - Day 3
Collection as an Abstract Class • Template methods defined in terms of do: • select:, collect:, inject:into:, detect:ifAbsent:, size Object-oriented Programming and Design - Johnson & Yoder - Day 3
Abstract class as type • All collections understand same protocol • do: iterate • select: subcollection • collect: transformed collection • inject:into: reduce collection to value • includes: does receiver contain it? • detect: find an element Object-oriented Programming and Design - Johnson & Yoder - Day 3
Finding an element • numbers do: [:each | each isOdd ifTrue: [^firstOdd := each]]. • … firstOdd ... • numbers do: [:each | each isOdd ifTrue: [firstOdd ifNil ifTrue: [firstOdd := each]]] • firstOdd := numbers detect: [:each | each isOdd] Object-oriented Programming and Design - Johnson & Yoder - Day 3
Find an Element • detect: aBlock ifNone: exceptionBlock • "Evaluate aBlock with each of the receiver's elements as the argument. Answer the first element for which aBlock evaluates to true." • self do: [:each | (aBlock value: each) • ifTrue: [^each]]. • ^exceptionBlock value Object-oriented Programming and Design - Johnson & Yoder - Day 3
Transform a Collection • collect: aBlock • | newCollection | • newCollection := self species new. • self do: [:each | newCollection add: (aBlock value: each)]. • ^newCollection Object-oriented Programming and Design - Johnson & Yoder - Day 3
Nonuniform Collection Protocol • add: and remove: are defined by collections whose size can change---Set, OrderedCollection, Bag, etc. • ArrayedCollection and Interval do not implement add: and remove: • at: and at:put: are defined by SequenceableCollection and Dictionary, but not by Set or Bag. Object-oriented Programming and Design - Johnson & Yoder - Day 3
Collection Protocols • Collection do:, size, select:, collect:, inject:into:, includes:, detect: • ChangeableCollection add: addAll: remove: removeAll: • SequenceableCollection at: at:put first last , copyFrom:to: Object-oriented Programming and Design - Johnson & Yoder - Day 3
Collection Menagerie • Array, String • Seq. • Symbol • Seq., read-only, unique • OrderedCollection • Seq., Changeable., a sequence • Set, Bag • Changeable Object-oriented Programming and Design - Johnson & Yoder - Day 3
Collection Menagerie • Dictionary • at: and at:put: with any object as key • Interval • Seq., numeric, read-only • RunArray • Seq., compact encoding Object-oriented Programming and Design - Johnson & Yoder - Day 3
OrderedCollection Instance variables: firstIndex, lastIndex A changeable sequenceable collection. Supports add:, remove:, at:, at:put: Object-oriented Programming and Design - Johnson & Yoder - Day 3
OrderedCollection • at: anInteger • anInteger isInteger ifFalse: [ ^...]. • (anInteger < 1 or: [anInteger + firstIndex - 1 > lastIndex]) • ifTrue: [^...] • ^ super at: anInteger + firstIndex - 1 Object-oriented Programming and Design - Johnson & Yoder - Day 3
OC::do: • do: aBlock • firstIndex to: lastIndex do: • [:index | aBlock value: (self basicAt: index)]. • size • ^ lastIndex - firstIndex + 1 Object-oriented Programming and Design - Johnson & Yoder - Day 3
OC::add: • add: newObject • "Include newObject as one of the receiver's elements. Answer newObject." • ^ self addLast: newObject Object-oriented Programming and Design - Johnson & Yoder - Day 3
OC::add: • addLast: newObject • "Add newObject to the end of the receiver. Answer newObject." • lastIndex = self basicSize ifTrue: [self makeRoomAtLast]. • lastIndex lastIndex + 1. • self basicAt: lastIndex put: newObject. • ^ newObject Object-oriented Programming and Design - Johnson & Yoder - Day 3
Using OrderedCollections • Suppose that list is an ordered collection. We want newList to be the reverse of list. • solution 1 • newList := OrderedCollection new. • list do: [:each | newList addFirst: each] Object-oriented Programming and Design - Johnson & Yoder - Day 3
(continued) • solution 2 • newList := OrderedCollection newWithSize: list size. • index := list size. • list do: [:each | newList at: index put: each. • index := index - 1] Object-oriented Programming and Design - Johnson & Yoder - Day 3
Interval • Instance variables: start, stop, step • 1 to: 1000 • 1 to: 1000 by: 3 • 1 to: 1000 do: [:each | sum sum + each] Object-oriented Programming and Design - Johnson & Yoder - Day 3
Interval • Number • to: stop • ^ Interval from: self to: stop by: 1 Object-oriented Programming and Design - Johnson & Yoder - Day 3
Interval do: • do: aBlock • | n end | • n := 0. • end := self size - 1. • [n <= end] • whileTrue: • [aBlock value: start + (step * n). • n := n + 1] Object-oriented Programming and Design - Johnson & Yoder - Day 3
Interval do: • do: aBlock • | aValue | • aValue := start. • step < 0 • ifTrue: [[stop <= aValue] • whileTrue: • [aBlock value: aValue. • aValue := aValue + step]] • ifFalse: [[stop >= aValue] • whileTrue: • [aBlock value: aValue. • aValue := aValue + step]] Object-oriented Programming and Design - Johnson & Yoder - Day 3
Interval at: • at: anInteger • (anInteger >= 1 and: [anInteger <= self size]) • ifTrue: [^start + (step * (anInteger - 1))] • ifFalse: [^self subscriptBoundsError: anInteger] Object-oriented Programming and Design - Johnson & Yoder - Day 3
Interval at:put: • at: anInteger put: anObject • "Provide an error notification that storing into an Interval is not allowed. " • self error: 'you can not store into an interval' Object-oriented Programming and Design - Johnson & Yoder - Day 3
Set 3 19 $x 11 'hi!' A hash table. nil means an unused entry. Instance variables: tally Object-oriented Programming and Design - Johnson & Yoder - Day 3
Hash • Sets and Dictionaries depend on the hash of their elements. • Each object has an integer hash value. • Some classes redefine hash. • Invariant: Equal (=) objects hash equally. Object-oriented Programming and Design - Johnson & Yoder - Day 3
Classic Set Bugs • Some classes redefine hash. • Invariant: Equal (=) objects hash equally. • Bug 1: redefine = but not hash for some class. • aSet add: x. • x = y • ifTrue: [(aSet includes: y) • ifFalse: [self error]] Object-oriented Programming and Design - Johnson & Yoder - Day 3
SequenceableCollection • = otherCollection • self == otherCollection ifTrue: [^ true]. • self species == otherCollection species • ifFalse: [^ false]. • ^ self hasEqualElements: otherCollection Object-oriented Programming and Design - Johnson & Yoder - Day 3
SequenceableCollection • hash • | hash | • hash := self species hash. • 1 to: self size • do: [:i | hash := (hash + (self at: i) hash) hashMultiply]. • ^hash Object-oriented Programming and Design - Johnson & Yoder - Day 3
Set bugs • Bug 2: Define = so it depends on state of the object. • Put object in set, then change its state, then try to find it! • Rule of thumb: only redefine = if object is immutable. Object-oriented Programming and Design - Johnson & Yoder - Day 3
Set do: • do: aBlock • tally == 0 ifTrue: [^self]. • 1 to: array size do: • [:index | • | each | • (each := array at: index) ifNotNil: [aBlock value: each]] Object-oriented Programming and Design - Johnson & Yoder - Day 3
Set includes: • includes: anObject • "Answer whether anObject is one of the receiver's elements." • ^(array at: (self findElementOrNil: anObject)) notNil Object-oriented Programming and Design - Johnson & Yoder - Day 3
Set • findElementOrNil: anObject • "Answer the index of a first slot containing either a nil (indicating an empty slot) or an element that matches the given object. Answer the index of that slot or zero. Fail if neither a match nor an empty slot is found.” • | index | • index := self scanFor: anObject. • index > 0 ifTrue: [^index]. • self error: 'There is no free space in this set!'. Object-oriented Programming and Design - Johnson & Yoder - Day 3
scanFor: anObject • | element start finish | • finish _ array size. • start _ (anObject hash \\ finish) + 1. • "Search from (hash mod size) to the end." • start to: finish do: • [:index | ((element _ array at: index) == nil or: [element = anObject]) • ifTrue: [^ index ]]. • "Search from 1 to where we started." • 1 to: start-1 do: • [:index | ((element _ array at: index) == nil or: [element = anObject]) • ifTrue: [^ index ]]. • ^ 0 "No match AND no empty slot" Object-oriented Programming and Design - Johnson & Yoder - Day 3
Classic Collection Bugs • add: returns argument • (aSet add: 3) add: 2 --- wrong • aSet add: 3; add: 2 --- right • How are these different? • Array with: 3 with: 17 with: -9 • #(3 17 -9) Object-oriented Programming and Design - Johnson & Yoder - Day 3
Conclusion • Collection is a typical class hierarchy • abstract classes on top • important interfaces, not completely regular • Missing ChangeableCollection • make assumptions (hash, =) about other classes Object-oriented Programming and Design - Johnson & Yoder - Day 3