Object Oriented Programming (OOP) in R with S3, S4, and RC

This TechVidvan article will give you the much-needed knowledge of object-oriented programming techniques to make your R programs more efficient and readable.

In this tutorial, we will go to the basics of object-oriented programming (OOP). We will study what are object-oriented and functional programming techniques and then look at how we can implement them in R programs. We will also take a look at various OOP approaches used in R.

So, let’s get started!

What is Object-Oriented Programming?

Object-oriented programming is a programming technique that manages the complexity of a program more efficiently. It uses techniques like abstraction, encapsulation, and polymorphism. It enacts an environment where the tasks are distributed among the different parts of the program or ‘objects’. These objects hide their internal working from other objects and only share concise details regarding what they can do and how to contact them.

For example, think of it as a company. A company may have different departments dealing with different aspects of it. One department does not share its internal workings with another. All a department needs to know is what the other departments do and how to get their help when needed. How a department does whatever it does, is not a concern to the others. This way, the tasks are distributed to appropriate departments and they all focus only on their jobs.

Similarly, in an object-oriented environment, we can think of the programs as interactions between different objects instead of steps of an algorithm.

What is Functional Programming?

Functional programming is a declarative programming style. It uses expressions that it evaluates to produce their values. Statements assign variables and expressions can be grouped together as functions to make organized routines of expressions. Functional programming is algorithmic.

Functional vs Object-Oriented Programming

Here are the key differences between functional and object-oriented programming:

  1. In functional programming, the primary unit is a function while in OOP, the primary unit is an object.
  2. Functional programming focuses on evaluating functions whereas OOP deals with objects and their interactions among each other.
  3. Data in functional programming is immutable that is when we modify data (which can be a function or a variable) the data is not simply modified. It is copied and the new copy has the changes made while the old copy is still saved in the memory. OOP has mutable data.
  4. Functional programming uses recursion for iterative processing while OOP uses loops for it.
  5. Functional programming supports parallel programming. Its functions do not affect code running on other processors. Object-oriented programming does not support parallel programming. Its methods may affect parallelly running parts of the program.
  6. In functional programming, statements can be executed in any order whereas in OOP, execution needs to be in a specific order.

Learn how loops work in R programming with examples.

Core Concepts of Object-Oriented Programming

Object-oriented programming has a few core techniques that distinguish it from other programming paradigms. Most OOP languages don’t implement all of them but just some of these techniques instead. The most common ones are:

  1. Polymorphism: Polymorphism means different shapes. In polymorphism, a single name can be used to call different objects based on the context it is used in. Overloading and overriding are good examples of polymorphism techniques.
  2. Encapsulation: Encapsulation deals with abstraction. It ensures that the data encapsulated inside an object is not visible to other objects. Only the data and methods declared to be public knowledge are known to others.
  3. Hierarchies: In OOP, hierarchies can be of two types: Inheritance or Composition.
    • Inheritance is when a class is a ‘type of’ or a ‘special case of’ another class known as the superclass. For example, an eagle is a type of bird. Here, eagle is a subclass and bird is its superclass.
    • In Composition, a class has an instance of another class. For example, a car has wheels but wheels are not a type of car. There is no inheritance here but wheels are a part of the car so the class car should have access to the class wheels which implies composition.

Object-Oriented Programming in R

In R, we solve problems by dividing them into simpler functions and not objects. Hence, functional programming is generally used in R. OOP languages have a single object model in place. These models define the properties and behavior of the objects we create. R has a few different object-oriented programming systems or object models in place. These systems are:

  1. S3: S3 is the first and the simplest OOP system in R. It does not have many restrictions and we can create objects by simply adding a class attribute to it. S3 classes don’t have a formally defined structure. The methods defined in an S3 class belong to generic functions.
  2. S4: S4 classes have a definitive structure to them. This means that different S4 classes have a similar structure. We use the setClass() function to create a new class and the new() function to create an object. Like S3 classes, methods in S4 classes belong to generic functions rather than the classes themselves.
  3. Reference classes(RC): Reference classes in R are similar to object-oriented classes in other programming languages. They have all the features of S4 classes with an added environment. To create a reference class, we use the setRefClass() function. The methods in a reference class belong to the class itself.

While these three systems are in the base R packages, there are other packages on CRAN repository that provide more systems like the R6.

object oriented programming in R

Generic Functions

Generic functions are a topic of much confusion in R. These functions are good examples of polymorphism. The most common example of a generic function is the print() function.

The function prints the arguments provided. The input argument can be a string, a numeric or even an object. It does not need a description of the object, its type or structure. How does it do that? The print() function is a collection of various print functions dedicated to different data types and data structures in R. When we use it, the function finds the type and class of the input object and calls the appropriate function to print it. We can see the different functions under the generic print() function by using the method() command. For example:

Code:

methods(print)

Output:

[1] print.acf*
[2] print.anova*
[3] print.aov*
[4] print.aovlist*
.
.
.
[189] print.xgettext*
[190] print.xngettext*
[191] print.xtabs*
see ‘?methods’ for accessing help and source code

method(print) (1) - OOP in R

S3 Classes

S3 classes are the most basic object-oriented classes in R. They implement the polymorphism principle of OOP but not much else. To create an S3 class, we need to add a class attribute to an object.

Code:

emp <- list(name="ramesh",age="24",
department="sales",emp_id="00495")
class(emp) <- "employee"
emp

Output:

OOP in r - creating S3 class (1)

We can create methods for generic functions as well.

Code:

print.employee <- function(obj){
  cat("name: " ,obj$name, "\n")
  cat("age: ", obj$age, "\n")
  cat("department: ", obj$department, "\n")
  cat("Id: ", obj$emp_id, "\n")
}
print(emp)

Output:

S3 generic methods print.employee - object oriented programming in R

Don’t know how to write functions in R? Learn with user-defined functions in R.

Useful Functions for S3 Objects

1. The is.object() function: the is.object() function returns TRUE if the input argument is an object of any of the object models of R.

Code:

is.object(emp)

Output:

useful s3 functions is.object() (1) - object oriented programming in r

2. The getS3method() function: the getS3method() function returns the S3 method used by a generic function for a specific type of object.

Code:

getS3method('print','employee')

Output:

useful S3 functions getS3method() (1) - object oriented programming in r

S4 Classes

S4 classes take OOP in R one step further than S3 classes. They have a definite structure to them which brings some uniformity to objects in R. We can create an S4 class by using the setClass() function and make a new object using the new function.

Code:

setClass("employeeS4", slots=list(name=
"character",age="numeric",department=
"character",emp_id="numeric"))
emp2 <- new("employeeS4",name="james",age=27,
department="accounts",emp_id=00564)
emp2

Output:

creating S4 class and object (1) - object oriented programming in r

Confused about the list in R? Learn to create R list again.

We can access and modify the slots of an S4 object using the @ or the slot() function.

Code:

emp2@name

Code:

emp2@name <- "jerry"
emp2@name

Code:

slot(emp2,"age")

Code:

slot(emp2,"age") <- 28
slot(emp2,"age")

Output:

accessing and modify slots of an S4 objects - object oriented programming in r

We can create a method for a generic function for S4 classes using the setMethod() function.

Code:

setMethod("show",
"employeeS4",
function(object){
  cat("name: ", object@name, "\n")
  cat("age: ",object@age,"\n")
  cat("department: ",object@department,"\n")
  cat("Id: ",object@emp_id,"\n")
}
)

Code:

emp2

Output:

creating S4 method for generic functions - object oriented programming in r

Useful S4 Methods in R

Here are a few functions that are useful when dealing with S4 objects:

1. The isS4() function: the isS4() function returns TRUE if the input argument is an S4 object.

Code:

isS4(emp2)

Output:

useful S4 functions isS4() - object oriented programming in r

2. The slotNames() function: the slotNames() function returns the names of all the slots in the input object.

Code:

slotNames(emp2)

Output:

useful S4 functions slotNames() copy10 - object oriented programming in r

Reference Classes (RC)

Reference classes are like object-oriented classes in other programming languages. They have all the properties of S4 classes with some added structure and restrictions. We can create a reference class using the setRefClass() function.

Code:

employeeRC <- setRefClass("employeeRC",
fields=list(name="character",age="numeric",
department="character",emp_id="numeric"))
emp3 <- employeeRC(name="rahul",age=25,
department="human resources",emp_id=00243)
emp3

Output:

creating a reference class - object oriented programming in r

We can access and modify the field in a reference class using the $ symbol.

Code:

emp3$name

Code:

emp3$name <- "suman"
emp3$name

Output:

accessing and modifying fields in RC - object oriented programming in r

We can define methods for reference classes using the methods argument of the setRefClass() function.

Code:

employeeRC <- setRefClass("employeeRC",
fields=list(name="character",age="numeric",
department="character",emp_id="numeric"),
methods=list(
show = function(){
  cat("name: ", name, "\n")
  cat("age: ", age,"\n")
  cat("department: ", department,"\n")
  cat("Id: ", emp_id,"\n")
}
))
emp4 <- employeeRC(name="jimmy",age=26,department="RnD"
,emp_id=00342)
show(emp4)

Output:

methods for RC - object oriented programming in r

Summary

In this tutorial, we learned about Object-oriented programming in R. We learned what object-oriented programming and functional programming are.

We looked at the various object models in R programming, how they are different from one another, and We saw how we can create classes and objects in these different models. We also learned what generic functions are. Finally, we looked at a few examples of S3, S4 and RC classes and their methods.

Any doubts while executing Object-oriented programming in R?

Ask TechVidvan below.

Happy Learning!!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.