R Inheritance

One the main concept of object oriented programming is inheritance which allows us to define a new class of existing classes. This means that we can derive new classes from existing base classes and adding new features. Hence, inheritance provides re-usability of code.

Inheritance in S3 class

Since S3 classes do not have any fixed definition. Hence attributes of S3 objects can be arbitrary. As we know, derived class inherits the methods defined for base class. For example, we have a function that creates new objects of class student as follows:
student <- function(n,a,g) {

  value <- list(name=n, age=a, GPA=g)

  attr(value, "class") <- "student"

  value

}
And we have a method defined for generic function print() as follows:
print.student <- function(obj) {

  cat("Name:", obj$name, "\n")

  cat("Age:", obj$age, "years old\n")

  cat("GPA:", obj$GPA, "\n")

}

Now, we want to create an object of the class InternationalStudent which inherits from student. This is be done by assigning a character vector of class names like class(obj) <- c(child, parent).
Example:
# create a list

s <- list(name="Nikita", age=21, GPA=8.5, country="France")

# make it of the class InternationalStudent which is derived from the class student

class(s) <- c("InternationalStudent","student")

# print it out

s
Output:
Name: Nikita

Age: 21 years old

GPA: 8.5

From the above example we can see that, since we have not defined any method of the form print.InternationalStudent(), the method print.student() got called. This method of class student was inherited. Now, let us define print.InternationalStudent():
print.InternationalStudent <- function(obj) {

  cat(obj$name, "is from", obj$country, "\n")

}

s
Output:
Nikita is from France

Inheritance in S4 Class

Since S4 classes have proper definition, derived classes will inherit both attributes and methods of the parent class. Let’s define a class student with a method for the generic function show():
# define a class called student

setClass("student",

         slots=list(name="character", age="numeric", GPA="numeric")

)

# define class method for the show() generic function

setMethod("show",

          "student",

          function(object) {

            cat(object@name, "\n")

            cat(object@age, "years old\n")

            cat("GPA:", object@GPA, "\n")

          }

)

Inheritance is done during the derived class definition with the argument contains:
# inherit from student

setClass("InternationalStudent",

         slots=list(country="character"),

         contains="student"

)
Here, new attribute is country; rest will be inherited from the parent.
s <- new("InternationalStudent",name="Nikita", age=24, GPA=8.5, country="France")

show(s)
Output:
Nikita

24 years old

GPA: 8.5

Inheritance in Reference Class

It is similar to S4 class.
Example: Let’s see an example of student reference class with two methods inc_age() and dec_age().
student <- setRefClass("student",

                       fields=list(name="character", age="numeric", GPA="numeric"),

                       methods=list(

                         inc_age = function(x) {

                           age <<- age + x

                         },

                         dec_age = function(x) {

                           age <<- age - x

                         }

                       )

)
Now we will inherit from this class. We also overwrite a method dec_age() to add an integrity check to make sure age is never negative.
InternationalStudent <- setRefClass("InternationalStudent",

                                    fields=list(country="character"),

                                    contains="student",

                                    methods=list(

                                      dec_age = function(x) {

                                        if((age - x)<0)  stop("Age cannot be negative")

                                        age <<- age - x

                                      }

                                    )

)
Let’s test it:
s <- InternationalStudent(name="Nikita", age=21, GPA=8.5, country="France")

s$dec_age(5)

s$age

s$dec_age(20)

s$age
Output:
[1] 16

Error in s$dec_age(20) : Age cannot be negative

[1] 16