R S3 Class

S3 class is the most popular class in the R programming language.

It is simple and easy to implement, so most of the classes that come predefined in R are of this type.


Create S3 Class and Object in R

Create S3 Class

First we create a list with various components then we create a class using the class() function. For example,

# create a list with required components
employee1 <- list(name = "Peter", age = 21, role = "Developer")

# form class of employee1 list and 
# name the class appropriately
class(employee1) <- "Employee_Info"

Here, first we have created a list named employee1 with required components.

Then we have formed a class of employee1 using class(employee1) and named the class Employee_Info.

Now we can create an object of this class.

Create S3 Object

An S3 object is basically a list with its class attributes assigned some names. We use the name of the list to create and call the object we created.

To create and call an object of the class above, we simply use the list name employee1. For example,

# create and call an object
employee1

Here, we have successfully created and called an object of the Employee_Info class.


Example: R S3 Class

# create a list with required components
employee1 <- list(name = "Peter", age = 21, role = "Developer")

# form class of employee1 list and 
# name the class appropriately
class(employee1) <- "Employee_Info"

# create and call an object
employee1

Output

$name
[1] "Peter"

$age
[1] 21

$role
[1] "Developer"

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

In the above example, we have created a list named employee1 with three components.

Here, Employee_Info is the name of the class. And to create an object of this class, we have passed the employee1 list inside class().

Finally, we have created an object of the Employee_Info class and called the object employee1.


S3 Generic Function and Method in R

A generic function is composed of multiple functions implementing the same operation for different types.

In the above example, we simply used the object name to print the class attributes. In interactive mode, writing the name alone will print it using the print() function.

# create and call object without print()
employee1

# create and call object with print()
print(employee1)

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

Furthermore, we can use print() with vectors, data frames, factors etc. and they get printed differently according to the class they belong to.

How does print() know how to print these varieties of dissimilar looking objects?

The answer is, print() is a generic function. Actually, it has a collection of a number of methods.

You can check all these methods using

# to display all available methods
methods(print)

Output

[1] print.Arima*                                        
[2] print.AsIs                                          
[3] print.Bibtex*
...
...
[184] print.xgettext*                                     
[185] print.xngettext*                                    
[186] print.xtabs*

Here, the methods() function will display all available, 186, methods of print.

We can see methods like print.factor and print.data.frame in the above list.

When we call print() on a factor, it is dispatched to print.factor(). Here, we can observe that the method names are in the form generic_name.class_name().

This is how R is able to figure out which method to call depending on the class.

Printing our object of class Employee_Info looks for a method of the form print.Employee_Info(), but there is no method of this form.

So, which method did our object of class Employee_Info call?

It called print.default(). This is the fallback method which is called if no other match is found. Generic functions have a default method.


Write Own Method in R

Since there is no print.Employee_Info() method as we discussed above. We will try to implement the method print.Employee_Info() ourselves.

print.Employee_Info <- function(obj) {
cat(obj$name, "\n")
cat(obj$age, "years old\n")
cat("Role:", obj$role, "\n")
}

Here, we have created a method named print.Employee_Info(). We have passed obj as an argument.

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

Now this method will be called whenever we print() an object of class Employee_Info.

# create a list with required components
employee1 <- list(name = "Peter", age = 21, role = "Developer")

# form class of employee1 list and 
# name the class appropriately
class(employee1) <- "Employee_Info"

print.Employee_Info <- function(obj) {
cat(obj$name, "\n")
cat(obj$age, "years old\n")
cat("Role:", obj$role, "\n")
}

print(employee1)

Output

Peter 
21 years old
Role: Developer

Here, whenever we print() an object of the Employee_Info class, print.Employee_Info() will be called.

We can also use the print.Employee_Info() method as

print.Employee_Info(employee1)

The output will be the same.