---
# System prepended metadata

title: Smalltalk Reflection Methods Review

---

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