# Smalltalk Reflection Methods Review All of these reflection methods have a class as its receiver. You can add a method, remove a method, get a method, or get a list of all methods of any class. **Terms**: - compiled method: these are methods that are _defined_ in the class. This does not include methods that are inherited. ## Adding a method to an existing class ### The method: > `addSelector:withMethod: aSymbol aCompiledMethod` Here's a breakdown of the arguments: 1. `aSymbol`: a symbol representing the method name 2. `aCompiledMethod`: a method formed using `compiled-method (args) body`. I'd like to think of it almost like a lambda (but not really). ### Example (taken from recitation): Let's say we want to add the ability to create a deep copy to the `List` class. If this method already existed in the `List` class, it would look something like this: ``` (method deepCopy () [local temp] (set temp (List withAll: self)) temp) ``` Now, since we can't explicitly go into the `List` class and change it, we can use `addSelector:withMethod:` to add this `deepCopy` method to the `List` class. Here's what it will look like: ``` (List addSelector:withMethod: 'deepCopy (compiled-method () [locals temp] (set temp (List withAll: self)) temp)) ``` ### Exercise: Who says you can't teach an old dog new tricks? We have a class appropriately named `OldDog`, whose definition looks like this: ``` (class OldDog [subclass-of Object] [ivars tricks full foods goodDog] (class-method new: (aSet) ((super new) init: aSet)) (method init: (ts) ;; private (set tricks ts) (set foods '(chicken carrot apple)) (set full false) (set goodDog 0) self) (method getTricks () tricks) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; some fun methods. Read at your leisure! ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (method doTrick: (trick) ((tricks includes: trick) ifTrue:ifFalse: { (set goodDog (goodDog + 1)) 'success-woof } { 'i-cannot-do-that-trick })) (method sleep () (set full false) 'zzzz) (method drink () 'slurp-slurp-slurp) (method isFull () full) (method eat: (aSymbol) (full ifTrue:ifFalse: { 'i-cannot-eat-anymore } { ((foods includes: aSymbol) ifTrue:ifFalse: { (set full true) 'yum! } { 'i-cannot-eat-this })})) (method isGoodDog () true) (method goodDogLevel () goodDog)) ``` Put this definition in a file named `olddog.smt`. Your task: Add a method `teach:` that takes in one parameter `newTrick` and adds the trick to the dog's list of tricks. Using `addSelector:withMethod:`, write your solution after the definition of the `OldDog` class. ### Testing your solution Add these few lines after your solution in `olddog.smt`: ``` (val oldDog (OldDog new: ((Set new) addAll: '(sit fetch speak)))) (oldDog teach: 'paw) (val expected ((Set new) addAll: '(sit fetch speak paw))) (check-expect (oldDog getTricks) expected) (oldDog teach: 'fetch) (check-expect (oldDog getTricks) expected) ``` The run: `usmalltalk < olddog.smt` # Addendum: Additional reflection methods that are good to know, but not necessary for this assignment ## Retrieve _all_ compiled methods from a class ### Method > `methodNames` ### Example ``` (List methodNames) -> ( at:put: lastKey firstKey removeKey:ifAbsent: remove:ifAbsent: removeLast removeLast removeFirst add: addFirst: addLast: do: last isEmpty sentinel: ) ``` ## Remove an existing method from a class ### Method > `removeSelector: aSymbol` Here's a breakdown of its argument: 1. `aSymbol`: The name of the method to be removed, if it exists. ### Example ``` (List removeSelector: 'at:put:) ``` ## Access a method from a class ### Method > `compiledMethodAt: aSymbol` Here's a breakdown of its argument: 1. `aSymbol`: The name of the method to be retrieved. If the method does not exist, it fails with a checked-runtime error. ### Example ``` (List compiledMethodAt: 'removeFirst) ```