The exercise is getting harder.

## OO field guide

### Base types & S3

- Read the source code for
`t()`

and`t.test()`

and confirm that`t.test()`

is an S3 generic and not an S3 method. What happens if you create an object with class test and call`t()`

with it?

`t`

```
## function (x)
## UseMethod("t")
## <bytecode: 0x0000000019ab3e08>
## <environment: namespace:base>
```

`t.test`

```
## function (x, ...)
## UseMethod("t.test")
## <bytecode: 0x00000000190b4970>
## <environment: namespace:stats>
```

`ftype(t)`

`## [1] "s3" "generic"`

`ftype(t.test)`

`## [1] "s3" "generic"`

Since object test does not have a method `t()`

associated with it. Calling `t()`

will call the default class.

- What classes have a method for the Math group generic in base R? Read the source code. How do the methods work?

`methods(Math)`

```
## [1] Math,nonStructure-method Math,structure-method
## [3] Math.data.frame Math.Date
## [5] Math.difftime Math.factor
## [7] Math.POSIXt
## see '?methods' for accessing help and source code
```

- R has two classes for representing date time data,
`POSIXct`

and`POSIXlt`

, which both inherit from`POSIXt`

. Which generics have different behaviours for the two classes? Which generics share the same behaviour?

Basically the generics of those two inherited classes that exist in `POSIXct`

share the same behavior. The generics that only exist in one class has different behavior.

`methods(class = "POSIXt")`

```
## [1] - + all.equal as.character Axis
## [6] coerce cut diff hist initialize
## [11] is.numeric julian Math months Ops
## [16] pretty quantile quarters round seq
## [21] show slotsFromS3 str trunc weekdays
## see '?methods' for accessing help and source code
```

`methods(class="POSIXct")`

```
## [1] [ [[ [<- as.data.frame as.Date
## [6] as.list as.POSIXlt c coerce format
## [11] initialize length<- mean print rep
## [16] show slotsFromS3 split summary Summary
## [21] weighted.mean xtfrm
## see '?methods' for accessing help and source code
```

`methods(class="POSIXlt")`

```
## [1] [ [[ [<- anyNA as.data.frame
## [6] as.Date as.double as.list as.matrix as.POSIXct
## [11] c coerce duplicated format initialize
## [16] is.na length length<- mean names
## [21] names<- print rep show slotsFromS3
## [26] sort summary Summary unique weighted.mean
## [31] xtfrm
## see '?methods' for accessing help and source code
```

- Which base generic has the greatest number of defined methods?

```
library(pryr)
objs <- mget(ls("package:base"), inherits = TRUE)
funs <- Filter(is.function, objs)
generics <- funs[sapply(funs, function(x) ("generic" %in% ftype(x)))]
names(generics)[which.max(sapply(names(generics), function(x) length(methods(x))))]
```

`## [1] "print"`

`UseMethod()`

calls methods in a special way. Predict what the following code will return, then run it and read the help for`UseMethod()`

to figure out what’s going on. Write down the rules in the simplest form possible.

```
y <- 1
g <- function(x) {
y <- 2
UseMethod("g")
}
g.numeric <- function(x) y
g(10)
```

`## [1] 2`

```
h <- function(x) {
x <- 10
UseMethod("h")
}
h.character <- function(x) paste("char", x)
h.numeric <- function(x) paste("num", x)
h("a")
```

`## [1] "char a"`

`g(10)`

will return 2. Since y is not in the function, it will search in `g`

`h(“a”)`

will return “char a” because “a” is a character. `h.numeric()`

will not be executed or further searched.

- Internal generics don’t dispatch on the implicit class of base types. Carefully read
`?“internal generic”`

to determine why the length of f and g is different in the example below. What function helps distinguish between the behaviour of`f`

and`g`

?

```
f <- function() 1
g <- function() 2
class(g) <- "function"
class(f)
```

`## [1] "function"`

`class(g)`

`## [1] "function"`

```
length.function <- function(x) "function"
length(f)
```

`## [1] 1`

`length(g)`

`## [1] "function"`

`length(f)`

will not search for `length.function`

thus “function” will not be returned unlike `length(d)`

. `f`

does not have a class associated with it so internal generics don’t dispatch on the implicit class of base types.

### S4

- Which S4 generic has the most methods defined for it? Which S4 class has the most methods associated with it?

```
generics<- getGenerics(where = search())
generics_s4 <- generics@.Data[sapply(generics@.Data, function(x) isS4(get(x)))]
generics_s4[which.max(sapply(generics_s4, function(x) length(methods(x))))]
```

`## [1] "coerce"`

```
s4class <- getClasses(where = .GlobalEnv, inherits = TRUE)
Methods <- sapply(s4class, function(x) showMethods(classes = x, printTo = FALSE))
names(Methods)[which.max(lapply(Methods, function(x) length(grep("Function", x))))]
```

`## [1] "ANY"`

- What happens if you define a new S4 class that doesn’t “contain” an existing class? (Hint: read about virtual classes in
`?setClass`

.)

In the latter case, a virtual class may include slots to provide some common behavior without fully defining the object—see the class traceable for an example. Note that “VIRTUAL” does not carry over to subclasses; a class that contains a virtual class is not itself automatically virtual.

- What happens if you pass an S4 object to an S3 generic? What happens if you pass an S3 object to an S4 generic? (Hint: read
`?setOldClass`

for the second case.)

### RC

- Use a field function to prevent the account balance from being directly manipulated. (Hint: create a “hidden” .balance field, and read the help for the fields argument in
`setRefClass()`

.)

Not sure

- I claimed that there aren’t any RC classes in base R, but that was a bit of a simplification. Use
`getClasses()`

and find which classes`extend()`

from`envRefClass`

. What are the classes used for? (Hint: recall how to look up the documentation for a class.)

```
classes <- getClasses(where = .GlobalEnv, inherits = TRUE)
classes[(sapply(classes, function(x) extends(x, "envRefClass")))]
```

`## [1] "envRefClass" "refGeneratorSlot" "localRefClass"`