R S4 Class

S4 class is an improvement over the S3 class. They have a formally defined structure and a uniform way to create an object.

This adds safety to our code and prevents us from accidentally making naive mistakes.


Define S4 Class in R

In R, we use the setClass() function to define a class.

Member variables in R are called slots. While defining a class, we need to set the name and the slots (along with class of the slot) it is going to have.For example,

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

Here, we have created a class named Employee_Info with three slots (member variables): name, age, and role.


Create S4 Object in R

To create an object in R, we use the new() function. For example,

student1 <- new("Student_Info", name = "Peter", age = 21, role = "Developer")

Here, we have created the object named student1 by providing the name of the class Student_Info and value for all three slots inside new().


Example 1: S4 Class and Object in R

# create a class "Student_Info" with three member variables
setClass("Employee_Info", slots=list(name="character", age="numeric", role="character"))

# create an object of class 
employee1 <- new("Employee_Info", name = "Peter", age = 21, role = "Developer")

# call employee1 object 
employee1

Output

An object of class "Employee_Info"
Slot "name":
[1] "Peter"

Slot "age":
[1] 21

Slot "role":
[1] "Developer"

Here, we have created an S4 class named Employee_Info using the setClass() function.

We then created an object named employee1 using the new() function

new("Employee_Info", name = "Peter", age = 21, role = "Developer")

Here,

  • name accepts "character" value so, we have passed "Peter"
  • age accepts "numeric" value, so we passed numeric value 21
  • role accepts "character" value so, we have passed "Developer"

Finally, we have called the object employee1.


Access S4 Class Slot in R

In R, we access slots using the @ operator. For example,

# access name slot of Employee_Info class
employee1@name # prints "Peter"

Here, we have accessed the name slot of the Employee_Info class using @.

So "Peter" gets printed.

Example: Access S4 Class slot

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

employee1 <- new("Employee_Info", name = "Peter", age = 21, role = "Developer")

# access name slot of Employee_Info 
employee1@name # prints "Peter"

# access role slot of Employee_Info
employee1@role # prints "Developer"

Output

[1] "Peter"
[1] "Developer"

Here,

  • employee1@name - access name slot of Employee_Info and prints "Peter"
  • employee1@role - access role slot of Employee_Info and prints "Developer"

Modify S4 Class Slot in R

We can use @ to access and assign a new value to a slot in R. For example,

# access and assign new value to role slot
employee1@role <- "Designer"

# print new slot value
employee@role

Here, the role slot value is changed from "Developer" to "Designer".

Example: Modify S4 Class slot

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

employee1 <- new("Employee_Info", name = "Peter", age = 21, role = "Developer")

# access and modify name slot of Employee_Info 
employee1@name <- "Jack" 

# access and modify role slot of Employee_Info
employee1@role <- "Designer"

# print modified value for name slot
employee1@name # prints "Jack"

# print modified value for role slot
employee1@role  # prints "Designer"

Output

[1] "Jack"
[1] "Designer"

Here,

  • employee1@name <- "Jack" - changes value of name slot from "Peter" to "Jack".
  • employee1@role <- "Designer" - changes role slot from "Developer" to "Designer".

S4 Generic Function and Method in R

As in the case of S3 class, methods for S4 class also belong to generic functions rather than the class itself.

Working with S4 generics is pretty much similar to S3 generics. So please visit S3 generics to get detailed information on generics.

We can list all the S4 generic functions and methods available, using the function showMethods():

# list all s4 generic methods
showMethods()

Output

Function: - (package base)
Function: != (package base)
...
...
Function: trigamma (package base)
Function: trunc (package base)

After creating an object of the class, when we just write the name of the object in interactive mode, it prints the object. This is done using the S4 generic function show().

You can see this function in the above list. This function is the S4 analogy of the S3 print() function.

# call object without show()
employee1

# call object with show()
show(employee1)

Here, in both case, the output will be the same

Example: Check if a function is a generic function

isS4(print)
# Output: [1] FALSE

isS4(show)
# Output: [1] TRUE

Here, we have used the isS4() function to check if a function is a S4 generic function or not.

Since,

  • print is not S4 generic function, the function returns FALSE
  • show is S4 generic function, the function returns TRUE

Write Own Method in R

In R, we can write our own method using the setMethod() function.

For example, we can implement our class method for the show() generic as follows.

setMethod("show",
"Employee_Info",

function(obj) {
cat(obj@name, "\n")
cat(obj@age, "years old\n")
cat("Role:", obj@role, "\n")
}
)

Here, we have implemented our class method for the show() generic.

Now, if we write out the name of the object in interactive mode as before, the above code is executed. For example,

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

employee1 <- new("Employee_Info", name = "Peter", age = 21, role = "Developer")

# create own method
setMethod("show",
"Employee_Info",

function(object) {
cat(object@name, "\n")
cat(object@age, "years old\n")
cat("Role:", object@role, "\n")
}
)

# call employee1 object 
employee1

Output

Peter 
21 years old
Role: Developer

Here, we have created our own method for the show() generic. We have passed object as an argument.

We have used object and @ to get values for name, age, and role attributes of the Employee_Info class.

Now this method will be called whenever we write an object name.

So the output will be:

Peter 
21 years old
Role: Developer

Instead of

An object of class "Employee_Info"
Slot "name":
[1] "Peter"

Slot "age":
[1] 21

Slot "role":
[1] "Developer"

Did you find this article helpful?