# 3 Coin Objects

## 3.1 Introduction

In this chapter we describe how to create object classes in R. Specifically, we will focus on the so-called **S3 classes** or S3 system.
This is one of the three types of Object Oriented (OO) systems available in R, and it is the most common among R packages.

## 3.2 Objects and Classes

In the previous chapter we learned how to create a `toss()`

function, and also how to document it with roxygen comments. We can invoke `toss()`

to generate a first series of five tosses, and then compute the proportion of heads:

```
# random seed
set.seed(534)
# five tosses
five <- toss(coin, times = 5)
five
#> [1] "heads" "heads" "tails" "tails" "heads"
# proportion of heads in five
sum(five == "heads") / length(five)
#> [1] 0.6
```

We can also get a second series of tosses, but this time involving tossing a coin six times. Similarly, we compute the proportion of heads:

```
# six tosses
six <- toss(coin, times = 6)
six
#> [1] "tails" "heads" "heads" "heads" "tails" "heads"
# prop of heads in six
sum(six == "heads") / length(five)
#> [1] 0.8
```

The above code works … except that there is an error; the number of heads in `six`

is being divided by 5 instead of 6. R hasn’t detected this error: it doesn’t know that the division has to be done using `length(six)`

.

Wouldn’t it be prefarable to have some mechanism that prevented this type of error from happening? Bugs will always be part of any programming activity, but it is better to minimize certain types of errors like the one above.

## 3.3 S3 Classes

R has two (plus one) object oriented systems, so it can be a bit intimidatin gwhen you read and learn about them for the first time.
The goal of this tutorial is not to make you an expert in all R’s OO systems, but to help you become familiar with the so-called *S3 class*.

**S3** implements a style of object oriented programming called generic-function OO. S3 uses a special type of function called a *generic* function that decides which method to call. Keep in mind that S3 is a very casual system: it does not really have a formal definition of classes.

S3 classes are widely-used, in particular for statistical models in the `"stats"`

package. S3 classes are very informal in that there is not a formal definition for an S3 class. Usually, S3 objects are built on top of lists, or atomic vectors with attributes. But you can also turn functions into S3 objects.

Note that in more formal OOP languages, all functions are associated with a class, while in R, only some are.

### 3.3.1 Making an object

To make an object an instance of a class, you just take an existing base object and set the `"class"`

attribute. You can do that during creation of the object with `structure()`

```
# object coin via structure()
coin1 <- structure(c("heads", "tails"), class = "coin")
coin1
#> [1] "heads" "tails"
#> attr(,"class")
#> [1] "coin"
```

You can also create an object first, and then specify its class with the function `class()`

:

```
# object coin via class()
coin2 <- c("heads", "tails")
class(coin2) <- "coin"
coin2
#> [1] "heads" "tails"
#> attr(,"class")
#> [1] "coin"
```

As any object in R, you can inspect the class `coin1`

, and `coin2`

with the `class()`

function:

You can also determine if an object inherits from a specific class using `inherits()`

Having a `"coin"`

object, we can pass it to the `toss()`

function to simulate flipping the coin:

## 3.4 A more robust `"coin"`

class

Let’s review our class `"coin"`

. The way we defined a coin object was like this:

While this definition is good to illustrate the concept of an object, its class, and how to define generic methods, it is a very loose-defined class. One could create a `"coin"`

out of `c('tic', 'tac', 'toe')`

, and then use `toss()`

on it:

We need a more formal definition of a coin. For instance, it makes more sense to require that a coin should only have two sides. In this way, the vector `ttt`

would not be a valid coin.

For convenience purposes, we can define a **class constructor** function to
initialize a `"coin"`

object:

## 3.5 Improving `"coin"`

objects

To implement the requirement that a coin must have two sides, we can add an *if* condition to check for the length of the input vector:

```
# constructor function (version 2)
coin <- function(object = c("heads", "tails")) {
if (length(object) != 2) {
stop("\n'object' must be of length 2")
}
class(object) <- "coin"
object
}
```

Let’s try our modified constructor function `coin()`

to create a virtual version of the US penny like the one in the image below:

```
# US penny
penny <- coin(c("lincoln", "shield"))
penny
#> [1] "lincoln" "shield"
#> attr(,"class")
#> [1] "coin"
```

Now let’s try `coin()`

with an invalid input vector. In this case, the constructor function will `stop()`

execution with an error message because the input argument has more than 2 elements.

```
# invalid coin
ttt <- c('tic', 'tac', 'toe')
coin(ttt)
#> Error in coin(ttt):
#> 'object' must be of length 2
```

Because the `toss()`

function simulates flips using `sample()`

, we can take advantage of the argument `prob`

to specify probabilities for each side of the coin. In this way, we can create *loaded* (i.e. biased) coins.

The way we are going to keep the probability of each side of the coin is with the use an objetc’s attributes. An example of an attribute is the class of an object. For example the class of our `"coin"`

objects:

Notice how everytime you print the name of a `"coin"`

object, its class is displayed in the form of `attr(,"class")`

.

### 3.5.1 Attributes

In addition to the class attribute of a coin, the idea is to assign another attribute for the probability values. We can do this by adding a `prob`

argument to the constructor function, and then pass it as an attribute of the coin object inside the class-constructor function.

```
# constructor function (version 3)
coin <- function(object = c("heads", "tails"), prob = c(0.5, 0.5)) {
if (length(object) != 2) {
stop("\n'object' must be of length 2")
}
attr(object, "prob") <- prob
class(object) <- "coin"
return(object)
}
coin()
#> [1] "heads" "tails"
#> attr(,"prob")
#> [1] 0.5 0.5
#> attr(,"class")
#> [1] "coin"
```

In the previous code, the `prob`

argument takes a vector of probabilities for each element in `object`

. This vector is passed to `object`

via the function `attr()`

inside the body of `coin()`

. Notice the use of a default `prob = c(0.5, 0.5)`

, that is, a *fair* coin by default.

### 3.5.2 Using a list

Another way to implement a constructor function `coin()`

that returns an object containing values for both the sides and the probabilities, is to use an R list. Here’s the code for this option:

```
# constructor function (version 4)
coin <- function(sides = c("heads", "tails"), prob = c(0.5, 0.5)) {
if (length(sides) != 2) {
stop("\n'sides' must be of length 2")
}
res <- list(sides = sides, prob = prob)
class(res) <- "coin"
return(res)
}
coin()
#> $sides
#> [1] "heads" "tails"
#>
#> $prob
#> [1] 0.5 0.5
#>
#> attr(,"class")
#> [1] "coin"
```

### 3.5.3 Auxiliary Checker

Once again, we need to check for the validity of `prob`

. We basically need to check that `prob`

and its elements meet the following requirements:

- must be numeric and of length 2
- probability values must be between 0 and 1
- the sum of these values must add up to 1

Here is one possible function to check the aspects of `prob`

listed above:

```
check_prob <- function(prob) {
if (length(prob) != 2 | !is.numeric(prob)) {
stop("\n'prob' must be a numeric vector of length 2")
}
if (any(prob < 0) | any(prob > 1)) {
stop("\n'prob' values must be between 0 and 1")
}
if (sum(prob) != 1) {
stop("\nelements in 'prob' must add up to 1")
}
TRUE
}
```

Note that I’m adding a `TRUE`

statement at the end of the function. This is just an auxiliary value to know if the function returns a valid `prob`

. Now let’s test it with *valid* and *invalid* values:

```
# Valid -----------------------
check_prob(c(0.5, 0.5))
#> [1] TRUE
check_prob(c(0.1, 0.9))
#> [1] TRUE
check_prob(c(1/3, 2/3))
#> [1] TRUE
check_prob(c(1/3, 6/9))
#> [1] TRUE
```

```
# Invalid -----------------------
# bad length
check_prob(1)
#> Error in check_prob(1):
#> 'prob' must be a numeric vector of length 2
# bad length
check_prob(c(0.1, 0.2, 0.3))
#> Error in check_prob(c(0.1, 0.2, 0.3)):
#> 'prob' must be a numeric vector of length 2
# negative probability
check_prob(c(-0.2, 0.8))
#> Error in check_prob(c(-0.2, 0.8)):
#> 'prob' values must be between 0 and 1
# what should we do in this case?
check_prob(c(0.33, 0.66))
#> Error in check_prob(c(0.33, 0.66)):
#> elements in 'prob' must add up to 1
```

Here’s the improved constructor function `coin()`

:

```
# constructor function (version 5)
coin <- function(sides = c("heads", "tails"), prob = c(0.5, 0.5)) {
if (length(sides) != 2) {
stop("\n'sides' must be of length 2")
}
check_prob(prob)
res <- list(sides = sides, prob = prob)
class(res) <- "coin"
return(res)
}
coin1 <- coin()
coin1
#> $sides
#> [1] "heads" "tails"
#>
#> $prob
#> [1] 0.5 0.5
#>
#> attr(,"class")
#> [1] "coin"
```

## 3.6 Print Method for `"coin"`

Every time you type in the name of an object `"coin"`

, like our `penny`

example, the output is displayed in a default, “quick and dirty”, way. R displays the values associated to the sides and their probabilities like any other list:

```
# US penny
penny <- coin(c("lincoln", "shield"))
penny
#> $sides
#> [1] "lincoln" "shield"
#>
#> $prob
#> [1] 0.5 0.5
#>
#> attr(,"class")
#> [1] "coin"
```

Sometimes the default displayed output is all you need. However, there are occasions in which you need to customize the amount and format of information displayed on the screen when you type in the name of an object.

Instead of keeping the default printed values, it would be nice to print `penny`

and see some *cleaner* output like this:

```
object "coin"
side prob
1 "lincoln" 0.5
2 "shield" 0.5
```

How can we do this? The answer involves writing a `print`

method for objects of class `"coin"`

. Because `print()`

is actually a generic function, what you need to do is to create a a specific print *flavor* for class `"coin"`

. Basically, you define a `print.coin()`

function, and then include commands to print information in the desired way:

```
# print method for objects of class "coin"
print.coin <- function(x) {
cat('object "coin"\n\n')
cd <- data.frame(
side = x$sides, prob = x$prob
)
print(cd)
invisible(x)
}
```

Now, the next time you print the name of an object of class `"coin"`

, R will look for a `print`

method (which now exists) and dispatch such method.

## 3.7 Extending classes

We can extend the class `"coin"`

and create a derived class for special types of coins. For instance, say we want to create a class `"quarter"`

. One side of the coin refers to George Washington, while the other side refers to the bald eagle:

https://en.wikipedia.org/wiki/Quarter_(United_States_coin)

We can create a quarter by first starting with a `coin()`

of `sides`

*washington* and *bald-eagle*, and then assign a `"quarter"`

class:

```
quarter1 <- coin(c("washington", "bald-eagle"))
class(quarter1) <- c("quarter", "coin")
quarter1
#> object "coin"
#>
#> side prob
#> 1 washington 0.5
#> 2 bald-eagle 0.5
```

Interestingly, our coin `quarter1`

inherits from `"coin"`

:

In other words, `quartier1`

is of class `"quarter"`

but it is also a `"coin"`

object.

Likewise, we can create a class for a slightly unbalanced `"dime"`

:

```
dime1 <- coin(c("roosevelt", "torch"), prob = c(0.48, 0.52))
class(dime1) <- c("dime", "coin")
dime1
#> object "coin"
#>
#> side prob
#> 1 roosevelt 0.48
#> 2 torch 0.52
```

Here’s another coin example, a *peso*, from Mexico (where I grew up). When you flip a *peso*, mexicans will talk about two sides: *aguila* (eagle) or *sol* (sun):

```
peso <- coin(c("aguila", "sol"))
class(peso) <- c("peso", "coin")
peso
#> object "coin"
#>
#> side prob
#> 1 aguila 0.5
#> 2 sol 0.5
```

#### Make a donation

If you find this resource useful, please consider making a one-time donation in any amount. Your support really matters.