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 (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:
The S3 system is R's original OOP system. It's a more informal system compared to S4 and R6.
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 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
The S4 system provides a more formal approach to OOP compared to S3.
S4 classes are defined using the setClass()
function:
setClass("Person", slots = list(name = "character", age = "numeric"))
john <- new("Person", name = "John", age = 30)
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)
R6 is the most recent OOP system in R, and it supports classical OOP concepts like public/private methods and reference semantics.
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()
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:
By understanding and leveraging these systems, you can implement more structured, modular, and maintainable code in R.
Creating and using classes in R programming:
setClass()
function from the methods
package.# Creating a simple class setClass("Person", slots = list(name = "character", age = "numeric"))
Methods and functions in R OOP:
setMethod()
.# Defining a method for the Person class setMethod("print", "Person", function(object) { cat("Name:", object@name, "\n") cat("Age:", object@age, "\n") })
S3 vs. S4 classes in R:
# 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)
Inheritance and polymorphism in R OOP:
# 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)
Defining and using generic functions in R:
# 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") })
Encapsulation in R OOP:
# 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)