# 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)
```