R
classes - S4
Feb 4, 2018     2 minutes read

1. Why would you use OOP in R?

Object oriented programming in R is unfortunately rather complicated comparing to Python (which seems to be the only reasonable alternative for data science programming).

However, there are certain cases when OOP may come up helpful:

2. Creating a new class in S4

Let’s define a new class:

setClass(
  Class = 'Polygon', 
  slots = c(x = 'numeric', y = 'numeric'),
)

where Polygon is it’s name and slots are it’s attributes.

A new instance of class Polygon:

w1 <- new('Polygon', x = 1:3, y = c(1, 1, 2))

3. Attributes

If you’ve ever wondered what @ in R means, here’s the answer:

slotNames(w1)
## [1] "x" "y"
w1@x  
## [1] 1 2 3
w1@y
## [1] 1 1 2

It provides access to inctance attributes. You can also overwrite current attributes simply with:

w1@x <- c(3, 2, 1)

4. Methods

Let’s create a simple method show which prints a description of our object.

setMethod(
  f = 'show',
  signature = c(object = 'Polygon'),
  function(object) {
    cat(sprintf('This is a polygon with %d sides.\n', length(object@x)))
    cat(sprintf('(%g, %g)', object@x, object@y))
    cat('\n')
  }
)

print(w1)
## This is a polygon with 3 sides.
## (3, 1) (2, 1) (1, 2)

Yes, so far OOP in R looks extremely complicated and non-intuitive comparing to Python.

5. Inheritance

A simple example of inheritance:

setClass(
  'Triangle',
  contains = 'Polygon',
  validity = function(object)
    if (length(object@x) != 3) "a triangle has three sides" else TRUE
)

t1 <- new('Triangle', x=c(1, 2, 3), y=c(1, 1, 3))
class(t1)
## [1] "Triangle"
## attr(,"package")
## [1] ".GlobalEnv"
show(t1)
## This is a polygon with 3 sides.
## (1, 1) (2, 1) (3, 3)

You can see that a new class Trinagle ingerits x and y attributes and show method from class Polygon. It also adds a validity check, which produces an error if the number of vertices is different than 3.