R Tutorial

Fundamentals of R

Variables

Input and Output

Decision Making

Control Flow

Functions

Strings

Vectors

Lists

Arrays

Matrices

Factors

DataFrames

Object Oriented Programming

Error Handling

File Handling

Packages in R

Data Interfaces

Data Visualization

Statistics

Machine Learning with R

Object-Oriented Programming in R

Object-Oriented Programming (OOP) is a programming paradigm based on the concept of "objects". In R, OOP can be achieved through three systems: S3, S4, and R6. Each system offers its way of defining and working with objects and methods.

In this tutorial, we'll provide a brief overview of each OOP system in R:

1. S3 System

The S3 system is R's original OOP system. It's a more informal system compared to S4 and R6.

Defining S3 Classes:

S3 doesn't have a formal class definition. Instead, an object is assigned to a class using the class() function:

obj <- list(name = "John", age = 30)
class(obj) <- "Person"

S3 Methods:

S3 uses generic functions to achieve polymorphism. A generic function decides which method to call based on the class of the argument:

# Define a method for the print generic for the "Person" class
print.Person <- function(x) {
  cat("Person's Name:", x$name, "\n")
  cat("Person's Age:", x$age, "\n")
}

print(obj)  # Calls print.Person method

2. S4 System

The S4 system provides a more formal approach to OOP compared to S3.

Defining S4 Classes:

S4 classes are defined using the setClass() function:

setClass("Person",
         slots = list(name = "character", age = "numeric"))

Creating S4 Objects:

john <- new("Person", name = "John", age = 30)

S4 Methods:

You can define methods for specific classes using setMethod():

setMethod("show",
          "Person",
          function(object) {
            cat("Person's Name:", object@name, "\n")
            cat("Person's Age:", object@age, "\n")
          })

show(john)

3. R6 System

R6 is the most recent OOP system in R, and it supports classical OOP concepts like public/private methods and reference semantics.

Defining R6 Classes:

You need the R6 package to define R6 classes:

library(R6)

Person <- R6Class("Person",
                  public = list(
                    name = NULL,
                    age = NULL,
                    initialize = function(name, age) {
                      self$name <- name
                      self$age <- age
                    },
                    print_info = function() {
                      cat("Person's Name:", self$name, "\n")
                      cat("Person's Age:", self$age, "\n")
                    }
                  ))

# Create R6 object
john <- Person$new("John", 30)

# Call R6 method
john$print_info()

Conclusion

R provides multiple systems for object-oriented programming, catering to different needs and complexities. The choice of system often depends on the task at hand:

  • S3: Good for quick, informal OOP.
  • S4: Provides more structure and formalism than S3.
  • R6: Suitable for more classical OOP with reference semantics and clear public/private distinctions.

By understanding and leveraging these systems, you can implement more structured, modular, and maintainable code in R.

  1. Creating and using classes in R programming:

    • In R, you can create classes using the setClass() function from the methods package.
    # Creating a simple class
    setClass("Person", slots = list(name = "character", age = "numeric"))
    
  2. Methods and functions in R OOP:

    • Methods are functions associated with a particular class. You can define methods using setMethod().
    # Defining a method for the Person class
    setMethod("print", "Person", function(object) {
      cat("Name:", object@name, "\n")
      cat("Age:", object@age, "\n")
    })
    
  3. S3 vs. S4 classes in R:

    • S3 and S4 are different systems for creating and using classes in R. S4 classes offer more formal class definitions and methods.
    # S3 class example
    my_s3_object <- structure(list(name = "John", age = 25), class = "Person")
    
    # S4 class example
    setClass("PersonS4", slots = list(name = "character", age = "numeric"))
    my_s4_object <- new("PersonS4", name = "John", age = 25)
    
  4. Inheritance and polymorphism in R OOP:

    • Inheritance allows a subclass to inherit properties and methods from a superclass. Polymorphism allows objects of different classes to be used interchangeably.
    # Defining a subclass inheriting from Person
    setClass("Employee", contains = "Person", slots = list(employeeID = "character"))
    
    # Polymorphism example
    my_person <- new("Person", name = "Alice", age = 30)
    my_employee <- new("Employee", name = "Bob", age = 25, employeeID = "E123")
    
    print(my_person)
    print(my_employee)
    
  5. Defining and using generic functions in R:

    • Generic functions are functions that can behave differently based on the class of the object passed to them.
    # Defining a generic function
    setGeneric("greet", function(object) standardGeneric("greet"))
    
    # Defining methods for the generic function
    setMethod("greet", "Person", function(object) {
      cat("Hello, ", object@name, "!\n")
    })
    
    setMethod("greet", "Employee", function(object) {
      cat("Greetings, Employee ", object@employeeID, "!\n")
    })
    
  6. Encapsulation in R OOP:

    • Encapsulation refers to restricting access to certain components of an object. In R, you can use accessors to control access to slots.
    # Defining a class with private slots
    setClass("PrivatePerson", representation(name = "character", age = "numeric"))
    
    # Defining an accessor method for age
    setGeneric("getAge", function(object) standardGeneric("getAge"))
    setMethod("getAge", "PrivatePerson", function(object) object@age)
    
    # Accessing the private slot using the accessor
    my_private_person <- new("PrivatePerson", name = "Mary", age = 28)
    age_value <- getAge(my_private_person)