Open In App

R-Object Oriented Programming

Last Updated : 12 Jun, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

In R, Object-Oriented Programming (OOP) uses classes and objects to manage program complexity. R is a functional language that applies OOP concepts. Class is like a car's blueprint, detailing its model, engine and other features. Based on this blueprint, we select a car, which is the object. Each car object has its unique traits. An object, also called an instance of a class, is created through instantiation. In R, the S3 and S4 classes are key for OOP. Before diving into these classes, let’s first understand the basics of classes and objects.

Class and Object

Class is the blueprint or a prototype from which objects are made by encapsulating data members and functions. An object is a data structure that contains some methods that act upon its attributes. 

R - Object Oriented ProgrammingGeeksforgeeks
R - Object Oriented Programming

S3 Class

S3 class does not have a predefined definition and is able to dispatch. In this class, the generic function makes a call to the method. Easy implementation of S3 is possible because it differs from the traditional programming language Java, C++ and C# which implements Object Oriented message passing.

1. Creating S3 Class

To create an object of this class we will create a list that will contain all the class members. Then this list is passed to the class() method as an argument.

Syntax: 

variable_name <- list(attribute1, attribute2, attribute3....attributeN)

Example: 

In the following code, a Student class is defined. An appropriate class name is given having attributes student's name and roll number. Then the object of the student class is created and invoked. 

R
a <- list(name="Adam", Roll_No=15)

class(a) <- "Student"

print(a)

Output:

$name
[1] "Adam"

$Roll_No
[1] 15

attr(, "class")
[1] "Student"

2. Generic Functions

The generic functions are a good example of polymorphism. To understand the concept of generic functions consider the print() function. The print() function is a collection of various print functions that are created for different data types and data structures in the R Programming Language. It calls the appropriate function depending on the type of object passed as an argument. We can see the various implementation of print functions using the methods() function.

Example: Seeing different types of the print function

R
methods(print)

Output:

Print methodsGeeksforgeeks
Print methods

Now let's create a generic function of our own. We will create the print function for our class that will print all the members in our specified format. But before creating a print function let's create what the print function does to our class.

 Example:

R
a = list(name="Adam", Roll_No=15)

class(a) = "Student"

print(a)

Output:

$name
[1] "Adam"

$Roll_No
[1] 15

attr(,"class")
[1] "Student"

Now let's print all the members in our specified format. Consider the below example -

Example:

R
print.Student <- function(obj){
  cat("name: " ,obj$name, "\n")
  cat("Roll No: ", obj$Roll_No, "\n")
}

print(a)

Output:

name: Adam
Roll No: 15

3. Attributes

Attributes of an object do not affect the value of an object, but they are a piece of extra information that is used to handle the objects. The function attributes() can be used to view the attributes of an object.

Examples: An S3 object is created and its attributes are displayed.

R
attributes(a)

Output:

$names
'name''Roll_No'
$class
'Student'

Also, we can add attributes to an object by using attr. 

R
attr(a, "age")<-c(18)
attributes(a)

Output:

$names
'name''Roll_No'
$class
'Student'
$age
18

4. Inheritance in S3 Class

Inheritance is an important concept in OOP(object-oriented programming) which allows one class to derive the features and functionalities of another class. This feature facilitates code-reusability.

S3 class in R programming language has no formal and fixed definition. In an S3 object, a list with its class attribute is set to a class name. S3 class objects inherit only methods from their base class.

Example: 

In the following code, inheritance is done using S3 class, firstly the object is created of the class student.

R
student <- function(n, r){
    value <- list(name = n, Roll = r)
    attr(value, "class") <- "student"
    value
}

Then, the method is defined to print the details of the student. 

R
print.student <- function(obj){
    cat("Name:", obj$name, "\n")
    cat("Roll", obj$Roll_No, "\n")
}

Now, inheritance is done while creating another class by doing class(obj) <- c(child, parent).

R
s <- list(name="Kesha", Roll_No=21, country="India")

class(s) <- c("Student", "student")
print.Student(s)

Output: 

Name: Kesha
Roll: 21

The following code overwrites the method for class students.

R
print.student <- function(obj) {
    cat(obj$name, "is from", obj$country, "\n")
}
print.student(s)

Output:

Kesha is from India

S4 Class 

S4 class has a predefined definition. It contains functions for defining methods and generics. It makes multiple dispatches easy. This class contains auxiliary functions for defining methods and generics.

1. Creating S4 class and object 

setClass() command is used to create S4 class. Following is the syntax for setclass command which denotes myclass with slots containing name and rollno.

Syntax: 

 setClass("myclass", slots=list(name="character", Roll_No="numeric"))  

The new() function is used to create an object of the S4 class. In this function, we will pass the class name as well as the value for the slots.

Note: $ operator not defined for this S4 class , so we will use @ operator instead.

Example: 

R
setClass("Student", slots=list(name="character", Roll_No="numeric"))

a <- new("Student", name="Adam", Roll_No=20)

# Custom print method for S4 object
setMethod("print", "Student", function(x) {
    cat("name:", x@name, "\n") 
    cat("Roll No:", x@Roll_No, "\n")
})

print(a)

Output: 

name: Adam
Roll No: 20

2. Create S4 objects from the generator function

setClass() returns a generator function that helps in creating objects and it acts as a constructor.

Example:

R
stud <- setClass("Student", slots=list(name="character",
                               Roll_No="numeric"))

print(stud)

Output:

new("classGeneratorFunction", .Data = function (...)
new("Student", ...), className = structure("Student", package = ".GlobalEnv"),
package = ".GlobalEnv")

Now the above-created stud function will act as the constructor for the Student class. It will behave as the new() function.

Example:

R
# Custom Show method
setMethod("show", "Student", function(object) {
  cat("name:", object@name, "\n")  # Use @ to access slots
  cat("Roll No:", object@Roll_No, "\n")  # Use @ to access slots
})

x <-stud(name="Adam", Roll_No=15)

show(x)

Output:

name: Adam
Roll No: 15

3. Inheritance in S4 class

S4 class in R programming have proper definition and derived classes will be able to inherit both attributes and methods from its base class. For this, we will first create a base class with appropriate slots and will create a generic function for that class. Then we will create a derived class that will inherit using the contains parameter. The derived class will inherit the members as well as functions from the base class.

Example:

R
setClass("student",
         slots=list(name="character",
                    age="numeric", rno="numeric")
         )

setMethod("show", "student",
          function(obj){
              cat(obj@name, "\n")
              cat(obj@age, "\n")
              cat(obj@rno, "\n")
          }
          )

setClass("InternationalStudent",
         slots=list(country="character"),
         contains="student"
         )

s <- new("InternationalStudent", name="Adam",
          age=22, rno=15, country="India")
show(s)

Output:

Adam
22
15

Reasons for defining both S3 and S4 classes:

  • S4 Classes with S3 Generic Functions: If an S3 generic function is called directly, an S4 class will not be recognized unless that function is explicitly defined for S4 objects. For example, if a function like unique() from a package that does not implement it as an S4 generic is called, the S4 class will not be used.
  • Exceptions for Primitive Functions and Operators: Primitive functions and operators are exceptions to this rule. The internal C code will check if an object is of S4 class and, if so, will invoke the appropriate S4 method. This allows S4 method dispatch to take precedence for binary operator calls where at least one operand is an S4 object.
  • S3 vs. S4 Method Dispatch: If an eligible non-default S4 method is available, it will be used instead of the S3 method. This ensures that S4 methods are prioritized when both S3 and S4 methods exist for the same operation.

So if a package defined an S3 method for unique for an S4 class but another package defined an S4 method for a superclass of that class, the superclass method would be chosen, probably not what was intended.

In this article, we discussed Object-Oriented Programming (OOPs) in R Programming Language. We covered the S3 and S4 classes, the inheritance in these classes and the methods provided by these classes.


Next Article
Practice Tags :

Similar Reads