In R, object-oriented programming is implemented in several very different ways.
The S3 type of OO is the most used because it's very simple and yet does a good job at having what seems to be the same functions behave differently with different types of objects. A good reference is Advanced R by Hadley Wickham.
In R objects have attributes
. One of these attributes is the special class
attribute. You can see this with
x <- 1:3
y <- c(1, 2, 3)
class(x) # "integer"
class(y) # "numeric"
The S3 system is a function overloading system. A special function is defined, the generic. Then other functions, the methods, are defined to process objects depending or their classes. A method that must be defined is the default method.
Here I use your example to define first a generic and then the default method.
# Function 1
adding_1 <- function(x, ...) UseMethod("adding_1")
adding_1.default <- function(x, ...){
x <- x + 1
x
}
Now the methods for objects of class "list"
and "data.frame"
.
adding_1.list <- function(x, ...){
num <- sapply(x, is.numeric)
x[num] <- lapply(x[num], adding_1)
x
}
adding_1.data.frame <- function(x, ...){
num <- sapply(x, is.numeric)
x[num] <- lapply(x[num], adding_1)
x
}
And the same for subtracting_1
.
# Function 2
subtracting_1 <- function(x, ...) UseMethod("subtracting_1")
subtracting_1.default <- function(x){
x <- x - 1
x
}
subtracting_1.list <- function(x, ...){
num <- sapply(x, is.numeric)
x[num] <- lapply(x[num], subtracting_1)
x
}
subtracting_1.data.frame <- function(x, ...){
num <- sapply(x, is.numeric)
x[num] <- lapply(x[num], subtracting_1)
x
}
Test cases.
When called with x
as an argument (or y
above) it's the default method that is called since there is no adding_1.integer
nor adding_1.numeric
.
And the same goes for mat
.
But when called with a data frame, a special processing is needed in order not to have the function try to add 1
to character strings or other types of non-numeric column vectors that might be in the data frame.
mat <- matrix(1:6, 3)
df1 <- data.frame(x = letters[1:5], y = rnorm(5), z = 101:105)
adding_1(x)
adding_1(mat)
adding_1(df1)
subtracting_1(x)
subtracting_1(mat)
subtracting_1(df1)